From baa69a27adbddb6be4c1239303157444eee2fa33 Mon Sep 17 00:00:00 2001 From: Rahul Kothari Date: Fri, 7 Feb 2025 11:14:59 +0000 Subject: [PATCH 1/4] chore: Update migration_notes.md (#11801) Please read [contributing guidelines](CONTRIBUTING.md) and remove this line. --- docs/docs/migration_notes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/migration_notes.md b/docs/docs/migration_notes.md index bbfb931f172..483222a5a34 100644 --- a/docs/docs/migration_notes.md +++ b/docs/docs/migration_notes.md @@ -6,7 +6,7 @@ keywords: [sandbox, aztec, notes, migration, updating, upgrading] Aztec is in full-speed development. Literally every version breaks compatibility with the previous ones. This page attempts to target errors and difficulties you might encounter when upgrading, and how to resolve them. -### TBD +### 0.75.0 ### Changes to `TokenBridge` interface From b33f1da9438672766ae8e266b2aa3bf7b5a8964f Mon Sep 17 00:00:00 2001 From: Santiago Palladino Date: Fri, 7 Feb 2025 11:23:38 +0000 Subject: [PATCH 2/4] chore: Check versioning (#11611) Defines a set of values that identify the network: - L1 chain ID - L1 rollup contract - L2 protocol version - L2 circuits vk tree root (ie noir-circuits) - L2 protocol contracts tree root (ie noir-protocol-contracts) Returns these values as custom http headers on the json-rpc server, and all json-rpc clients now check those values. On mismatch, they throw. If a value is missing due to incomplete config, it is ignored. These values are also "compressed" (sliced and concatenated) and injected as a value in the node's ENR in the p2p layer. Nodes only connect to a bootstrap node if their versions matches the bootstrap node's ENR (they warn if they don't) and ignore peers (with debug level) if their ENRs don't match. Fixes #11577 Props to @Maddiaa0 for the help with the p2p side of things PR ended up larger than expected but commits are grouped together so that they can be reviewed one at a time. --------- Co-authored-by: Maddiaa --- spartan/aztec-network/templates/pxe.yaml | 2 + .../templates/transaction-bot.yaml | 2 + yarn-project/.gitignore | 1 + yarn-project/archiver/package.json | 1 + yarn-project/archiver/src/archiver/config.ts | 5 +- yarn-project/archiver/src/factory.ts | 10 +- yarn-project/archiver/src/rpc/index.ts | 19 ++- yarn-project/archiver/tsconfig.json | 3 + .../aztec-node/src/aztec-node/server.ts | 5 - .../aztec.js/src/api/ethereum/l1_contracts.ts | 2 +- .../aztec.js/src/rpc_clients/node/index.ts | 20 ++- .../aztec.js/src/rpc_clients/pxe_client.ts | 17 +- .../aztec/src/cli/aztec_start_action.ts | 21 +-- .../aztec/src/cli/cmds/start_archiver.ts | 7 +- yarn-project/aztec/src/cli/cmds/start_bot.ts | 2 +- yarn-project/aztec/src/cli/cmds/start_node.ts | 4 +- .../aztec/src/cli/cmds/start_p2p_bootstrap.ts | 1 + .../aztec/src/cli/cmds/start_prover_agent.ts | 3 +- .../aztec/src/cli/cmds/start_prover_broker.ts | 4 +- .../aztec/src/cli/cmds/start_prover_node.ts | 6 +- yarn-project/aztec/src/cli/cmds/start_pxe.ts | 15 +- yarn-project/aztec/src/cli/versioning.ts | 13 ++ yarn-project/aztec/src/sandbox.ts | 2 +- yarn-project/bootstrap.sh | 2 +- yarn-project/bot/package.json | 1 + yarn-project/bot/src/config.ts | 10 ++ yarn-project/bot/src/factory.ts | 4 +- yarn-project/bot/src/runner.ts | 5 +- yarn-project/bot/tsconfig.json | 3 + yarn-project/circuit-types/package.json | 1 + yarn-project/circuit-types/src/config.ts | 43 ++++- yarn-project/circuit-types/src/index.ts | 1 + .../src/interfaces/aztec-node.ts | 13 +- .../circuit-types/src/versioning.test.ts | 108 +++++++++++++ yarn-project/circuit-types/src/versioning.ts | 152 ++++++++++++++++++ .../infrastructure/setup_protocol_contract.ts | 2 +- yarn-project/cli/src/cmds/l1/advance_epoch.ts | 2 +- .../cli/src/cmds/l1/assume_proven_through.ts | 2 +- yarn-project/cli/src/utils/aztec.ts | 2 +- yarn-project/end-to-end/src/bench/utils.ts | 3 + .../composed/integration_l1_publisher.test.ts | 4 +- .../e2e_deploy_contract/deploy_method.test.ts | 2 +- .../src/fixtures/setup_l1_contracts.ts | 2 +- yarn-project/end-to-end/src/fixtures/utils.ts | 4 +- yarn-project/foundation/src/config/env_var.ts | 1 + .../foundation/src/json-rpc/client/fetch.ts | 4 +- .../json-rpc/client/safe_json_rpc_client.ts | 37 +++-- .../src/json-rpc/test/integration.test.ts | 6 +- .../src/json-rpc/test/integration.ts | 23 ++- .../scripts/generate-artifacts.sh | 13 +- .../noir-protocol-circuits-types/package.json | 3 +- .../src/artifacts/vks.ts | 83 ++++++++++ .../src/entrypoint/vks.ts | 130 ++------------- .../src/scripts/generate_vk_tree.ts | 54 +++++++ yarn-project/p2p/package.json | 2 + yarn-project/p2p/src/bootstrap/bootstrap.ts | 12 +- yarn-project/p2p/src/config.ts | 25 +-- yarn-project/p2p/src/mocks/index.ts | 13 +- .../p2p/src/services/discv5/discV5_service.ts | 81 ++++++++-- .../services/discv5/discv5_service.test.ts | 93 ++++++++--- .../reqresp/reqresp.integration.test.ts | 15 +- yarn-project/p2p/src/services/types.ts | 12 +- yarn-project/p2p/src/versioning.test.ts | 42 +++++ yarn-project/p2p/src/versioning.ts | 50 ++++++ yarn-project/p2p/tsconfig.json | 6 + .../src/block_builder/light.test.ts | 20 +-- .../prover-client/src/mocks/test_context.ts | 6 +- .../orchestrator/block-building-helpers.ts | 2 +- .../src/orchestrator/block-proving-state.ts | 30 ++-- .../src/orchestrator/epoch-proving-state.ts | 17 +- .../src/orchestrator/orchestrator.ts | 75 +++++---- ...rchestrator_multi_public_functions.test.ts | 2 +- .../orchestrator_public_functions.test.ts | 4 +- .../src/orchestrator/tx-proving-state.ts | 26 +-- .../prover-client/src/prover-agent/rpc.ts | 20 ++- .../prover-client/src/proving_broker/rpc.ts | 28 +++- .../src/test/bb_prover_full_rollup.test.ts | 2 +- .../src/test/bb_prover_parity.test.ts | 14 +- yarn-project/prover-node/package.json | 2 + yarn-project/prover-node/src/config.ts | 2 +- .../src/prover-coordination/factory.ts | 6 +- yarn-project/prover-node/tsconfig.json | 6 + yarn-project/pxe/src/bin/index.ts | 2 +- yarn-project/pxe/src/config/index.ts | 4 +- yarn-project/pxe/src/kernel_oracle/index.ts | 6 +- .../pxe/src/kernel_prover/kernel_prover.ts | 2 +- .../src/pxe_service/test/pxe_service.test.ts | 4 + yarn-project/sequencer-client/src/config.ts | 24 +-- yarn-project/yarn.lock | 7 + 89 files changed, 1136 insertions(+), 411 deletions(-) create mode 100644 yarn-project/aztec/src/cli/versioning.ts create mode 100644 yarn-project/circuit-types/src/versioning.test.ts create mode 100644 yarn-project/circuit-types/src/versioning.ts create mode 100644 yarn-project/noir-protocol-circuits-types/src/artifacts/vks.ts create mode 100644 yarn-project/noir-protocol-circuits-types/src/scripts/generate_vk_tree.ts create mode 100644 yarn-project/p2p/src/versioning.test.ts create mode 100644 yarn-project/p2p/src/versioning.ts diff --git a/spartan/aztec-network/templates/pxe.yaml b/spartan/aztec-network/templates/pxe.yaml index e54c6b0e192..fb18c519249 100644 --- a/spartan/aztec-network/templates/pxe.yaml +++ b/spartan/aztec-network/templates/pxe.yaml @@ -113,6 +113,8 @@ spec: value: "{{ .Values.telemetry.useGcloudObservability }}" - name: OTEL_EXCLUDE_METRICS value: "{{ .Values.telemetry.excludeMetrics }}" + - name: L1_CHAIN_ID + value: "{{ .Values.ethereum.chainId }}" ports: - name: http containerPort: {{ .Values.pxe.service.nodePort }} diff --git a/spartan/aztec-network/templates/transaction-bot.yaml b/spartan/aztec-network/templates/transaction-bot.yaml index a3f6f616eda..4de52c2836a 100644 --- a/spartan/aztec-network/templates/transaction-bot.yaml +++ b/spartan/aztec-network/templates/transaction-bot.yaml @@ -135,6 +135,8 @@ spec: value: "{{ .Values.telemetry.useGcloudObservability }}" - name: OTEL_EXCLUDE_METRICS value: "{{ .Values.telemetry.excludeMetrics }}" + - name: L1_CHAIN_ID + value: "{{ .Values.ethereum.chainId }}" ports: - name: http containerPort: {{ .Values.bot.service.nodePort }} diff --git a/yarn-project/.gitignore b/yarn-project/.gitignore index 16913cbef7e..54f5fff14b9 100644 --- a/yarn-project/.gitignore +++ b/yarn-project/.gitignore @@ -41,6 +41,7 @@ noir-protocol-circuits-types/src/private_kernel_reset_data.ts noir-protocol-circuits-types/src/private_kernel_reset_vks.ts noir-protocol-circuits-types/src/private_kernel_reset_types.ts noir-protocol-circuits-types/src/client_artifacts_helper.ts +noir-protocol-circuits-types/src/vk_tree.ts noir-protocol-circuits-types/src/types/ ivc-integration/artifacts ivc-integration/src/types/ diff --git a/yarn-project/archiver/package.json b/yarn-project/archiver/package.json index 5bab49643e9..e6674259334 100644 --- a/yarn-project/archiver/package.json +++ b/yarn-project/archiver/package.json @@ -73,6 +73,7 @@ "@aztec/kv-store": "workspace:^", "@aztec/l1-artifacts": "workspace:^", "@aztec/noir-contracts.js": "workspace:^", + "@aztec/noir-protocol-circuits-types": "workspace:^", "@aztec/protocol-contracts": "workspace:^", "@aztec/telemetry-client": "workspace:^", "@aztec/types": "workspace:^", diff --git a/yarn-project/archiver/src/archiver/config.ts b/yarn-project/archiver/src/archiver/config.ts index 52a2aac3d72..2a28644ee2b 100644 --- a/yarn-project/archiver/src/archiver/config.ts +++ b/yarn-project/archiver/src/archiver/config.ts @@ -1,3 +1,4 @@ +import { type ChainConfig, chainConfigMappings } from '@aztec/circuit-types/config'; import { type L1ContractAddresses, type L1ContractsConfig, @@ -39,7 +40,8 @@ export type ArchiverConfig = { /** The max number of logs that can be obtained in 1 "getPublicLogs" call. */ maxLogs?: number; } & L1ReaderConfig & - L1ContractsConfig; + L1ContractsConfig & + ChainConfig; export const archiverConfigMappings: ConfigMappingsType = { archiverUrl: { @@ -67,6 +69,7 @@ export const archiverConfigMappings: ConfigMappingsType = { description: 'The max number of logs that can be obtained in 1 "getPublicLogs" call.', ...numberConfigHelper(1_000), }, + ...chainConfigMappings, ...l1ReaderConfigMappings, viemPollingIntervalMS: { env: 'ARCHIVER_VIEM_POLLING_INTERVAL_MS', diff --git a/yarn-project/archiver/src/factory.ts b/yarn-project/archiver/src/factory.ts index c210aae8261..cd1660a5182 100644 --- a/yarn-project/archiver/src/factory.ts +++ b/yarn-project/archiver/src/factory.ts @@ -1,5 +1,5 @@ import { type BlobSinkClientInterface } from '@aztec/blob-sink/client'; -import { type ArchiverApi, type Service } from '@aztec/circuit-types'; +import { type ArchiverApi, type Service, getComponentsVersionsFromConfig } from '@aztec/circuit-types'; import { type ContractClassPublic, computePublicBytecodeCommitment, @@ -12,7 +12,8 @@ import { type DataStoreConfig } from '@aztec/kv-store/config'; import { createStore } from '@aztec/kv-store/lmdb-v2'; import { TokenContractArtifact } from '@aztec/noir-contracts.js/Token'; import { TokenBridgeContractArtifact } from '@aztec/noir-contracts.js/TokenBridge'; -import { protocolContractNames } from '@aztec/protocol-contracts'; +import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vks'; +import { protocolContractNames, protocolContractTreeRoot } from '@aztec/protocol-contracts'; import { getCanonicalProtocolContract } from '@aztec/protocol-contracts/bundle'; import { type TelemetryClient, getTelemetryClient } from '@aztec/telemetry-client'; @@ -34,7 +35,10 @@ export async function createArchiver( await registerCommonContracts(archiverStore); return Archiver.createAndSync(config, archiverStore, { telemetry, blobSinkClient }, opts.blockUntilSync); } else { - return createArchiverClient(config.archiverUrl); + return createArchiverClient( + config.archiverUrl, + getComponentsVersionsFromConfig(config, protocolContractTreeRoot, getVKTreeRoot()), + ); } } diff --git a/yarn-project/archiver/src/rpc/index.ts b/yarn-project/archiver/src/rpc/index.ts index 3535b22b32a..c51da0a4335 100644 --- a/yarn-project/archiver/src/rpc/index.ts +++ b/yarn-project/archiver/src/rpc/index.ts @@ -1,9 +1,22 @@ -import { type ArchiverApi, ArchiverApiSchema } from '@aztec/circuit-types'; +import { + type ArchiverApi, + ArchiverApiSchema, + type ComponentsVersions, + getVersioningResponseHandler, +} from '@aztec/circuit-types'; import { createSafeJsonRpcClient } from '@aztec/foundation/json-rpc/client'; import { createTracedJsonRpcServer, makeTracedFetch } from '@aztec/telemetry-client'; -export function createArchiverClient(url: string, fetch = makeTracedFetch([1, 2, 3], true)): ArchiverApi { - return createSafeJsonRpcClient(url, ArchiverApiSchema, false, 'archiver', fetch); +export function createArchiverClient( + url: string, + versions: Partial, + fetch = makeTracedFetch([1, 2, 3], true), +): ArchiverApi { + return createSafeJsonRpcClient(url, ArchiverApiSchema, { + namespaceMethods: 'archiver', + fetch, + onResponse: getVersioningResponseHandler(versions), + }); } export function createArchiverRpcServer(handler: ArchiverApi) { diff --git a/yarn-project/archiver/tsconfig.json b/yarn-project/archiver/tsconfig.json index a4129646732..1b0928c365e 100644 --- a/yarn-project/archiver/tsconfig.json +++ b/yarn-project/archiver/tsconfig.json @@ -33,6 +33,9 @@ { "path": "../noir-contracts.js" }, + { + "path": "../noir-protocol-circuits-types" + }, { "path": "../protocol-contracts" }, diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index 8383dc7c2f7..3c874eb768e 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -164,11 +164,6 @@ export class AztecNodeService implements AztecNode, Traceable { const archiver = await createArchiver(config, blobSinkClient, { blockUntilSync: true }, telemetry); - // we identify the P2P transaction protocol by using the rollup contract address. - // this may well change in future - const rollupAddress = config.l1Contracts.rollupAddress; - config.transactionProtocol = `/aztec/tx/${rollupAddress.toString()}`; - // now create the merkle trees and the world state synchronizer const worldStateSynchronizer = await createWorldStateSynchronizer(config, archiver, telemetry); const proofVerifier = config.realProofs ? await BBCircuitVerifier.new(config) : new TestCircuitVerifier(); diff --git a/yarn-project/aztec.js/src/api/ethereum/l1_contracts.ts b/yarn-project/aztec.js/src/api/ethereum/l1_contracts.ts index 21f57a32d2a..38fd8de1bbc 100644 --- a/yarn-project/aztec.js/src/api/ethereum/l1_contracts.ts +++ b/yarn-project/aztec.js/src/api/ethereum/l1_contracts.ts @@ -4,7 +4,7 @@ import { retryUntil } from '@aztec/foundation/retry'; import { createPXEClient } from '../../rpc_clients/index.js'; export const getL1ContractAddresses = async (url: string): Promise => { - const pxeClient = createPXEClient(url); + const pxeClient = createPXEClient(url, {}); const response = await retryUntil( async () => { try { diff --git a/yarn-project/aztec.js/src/rpc_clients/node/index.ts b/yarn-project/aztec.js/src/rpc_clients/node/index.ts index 0c596beb524..2baede9b38e 100644 --- a/yarn-project/aztec.js/src/rpc_clients/node/index.ts +++ b/yarn-project/aztec.js/src/rpc_clients/node/index.ts @@ -1,6 +1,6 @@ -import { type PXE } from '@aztec/circuit-types'; +import { type ComponentsVersions, type PXE } from '@aztec/circuit-types'; import { jsonStringify } from '@aztec/foundation/json-rpc'; -import { type Logger } from '@aztec/foundation/log'; +import { type Logger, createLogger } from '@aztec/foundation/log'; import { NoRetryError, makeBackoff, retry } from '@aztec/foundation/retry'; import { Axios, type AxiosError } from 'axios'; @@ -33,9 +33,13 @@ async function axiosFetch(host: string, rpcMethod: string, body: any, useApiEndp const isOK = resp.status >= 200 && resp.status < 300; if (isOK) { - return resp.data; + const headers = { + get: (header: string) => + typeof resp.headers.get === 'function' ? resp.headers.get(header)?.toString() : undefined, + }; + return { response: resp.data, headers }; } else { - const errorMessage = `(JSON-RPC PROPAGATED) (host ${host}) (method ${rpcMethod}) (code ${resp.status}) ${resp.data.error.message}`; + const errorMessage = `Error ${resp.status} from json-rpc server ${host} on ${rpcMethod}: ${resp.data.error.message}`; if (resp.status >= 400 && resp.status < 500) { throw new NoRetryError(errorMessage); } else { @@ -51,7 +55,11 @@ async function axiosFetch(host: string, rpcMethod: string, body: any, useApiEndp * @param _logger - Debug logger to warn version incompatibilities. * @returns A PXE client. */ -export function createCompatibleClient(rpcUrl: string, logger: Logger): Promise { +export function createCompatibleClient( + rpcUrl: string, + logger: Logger = createLogger('aztecjs:pxe_client'), + versions: Partial = {}, +): Promise { // Use axios due to timeout issues with fetch when proving TXs. const fetch = async (host: string, rpcMethod: string, body: any, useApiEndpoints: boolean) => { return await retry( @@ -62,7 +70,7 @@ export function createCompatibleClient(rpcUrl: string, logger: Logger): Promise< false, ); }; - const pxe = createPXEClient(rpcUrl, fetch); + const pxe = createPXEClient(rpcUrl, versions, fetch); return Promise.resolve(pxe); } diff --git a/yarn-project/aztec.js/src/rpc_clients/pxe_client.ts b/yarn-project/aztec.js/src/rpc_clients/pxe_client.ts index f2afd1b3d7c..fb32a4ee823 100644 --- a/yarn-project/aztec.js/src/rpc_clients/pxe_client.ts +++ b/yarn-project/aztec.js/src/rpc_clients/pxe_client.ts @@ -1,5 +1,7 @@ +import { type ComponentsVersions, getVersioningResponseHandler } from '@aztec/circuit-types'; import { type PXE, PXESchema } from '@aztec/circuit-types/interfaces'; import { createSafeJsonRpcClient, makeFetch } from '@aztec/foundation/json-rpc/client'; +import { protocolContractTreeRoot } from '@aztec/protocol-contracts'; /** * Creates a JSON-RPC client to remotely talk to PXE. @@ -7,6 +9,17 @@ import { createSafeJsonRpcClient, makeFetch } from '@aztec/foundation/json-rpc/c * @param fetch - The fetch implementation to use. * @returns A JSON-RPC client of PXE. */ -export function createPXEClient(url: string, fetch = makeFetch([1, 2, 3], false)): PXE { - return createSafeJsonRpcClient(url, PXESchema, false, 'pxe', fetch); +export function createPXEClient( + url: string, + versions: Partial = {}, + fetch = makeFetch([1, 2, 3], false), +): PXE { + return createSafeJsonRpcClient(url, PXESchema, { + namespaceMethods: 'pxe', + fetch, + onResponse: getVersioningResponseHandler({ + l2ProtocolContractsTreeRoot: protocolContractTreeRoot.toString(), + ...versions, + }), + }); } diff --git a/yarn-project/aztec/src/cli/aztec_start_action.ts b/yarn-project/aztec/src/cli/aztec_start_action.ts index 72304b9642f..32968c449d6 100644 --- a/yarn-project/aztec/src/cli/aztec_start_action.ts +++ b/yarn-project/aztec/src/cli/aztec_start_action.ts @@ -1,5 +1,6 @@ import { deployInitialTestAccounts } from '@aztec/accounts/testing'; -import { AztecNodeApiSchema, PXESchema } from '@aztec/circuit-types'; +import { AztecNodeApiSchema, PXESchema, getVersioningMiddleware } from '@aztec/circuit-types'; +import { type ChainConfig } from '@aztec/circuit-types/config'; import { type NamespacedApiHandlers, createNamespacedSafeJsonRpcServer, @@ -15,6 +16,7 @@ import { dirname, resolve } from 'path'; import { createSandbox } from '../sandbox.js'; import { github, splash } from '../splash.js'; import { createAccountLogs, extractNamespacedOptions, installSignalHandlers } from './util.js'; +import { getVersions } from './versioning.js'; const packageJsonPath = resolve(dirname(fileURLToPath(import.meta.url)), '../../package.json'); const cliVersion: string = JSON.parse(readFileSync(packageJsonPath).toString()).version; @@ -23,6 +25,7 @@ export async function aztecStart(options: any, userLog: LogFn, debugLogger: Logg // list of 'stop' functions to call when process ends const signalHandlers: Array<() => Promise> = []; const services: NamespacedApiHandlers = {}; + let config: ChainConfig | undefined = undefined; if (options.sandbox) { const sandboxOptions = extractNamespacedOptions(options, 'sandbox'); @@ -61,7 +64,7 @@ export async function aztecStart(options: any, userLog: LogFn, debugLogger: Logg } else { if (options.node) { const { startNode } = await import('./cmds/start_node.js'); - await startNode(options, signalHandlers, services, userLog); + ({ config } = await startNode(options, signalHandlers, services, userLog)); } else if (options.proofVerifier) { const { startProofVerifier } = await import('./cmds/start_proof_verifier.js'); await startProofVerifier(options, signalHandlers, userLog); @@ -70,16 +73,16 @@ export async function aztecStart(options: any, userLog: LogFn, debugLogger: Logg await startBot(options, signalHandlers, services, userLog); } else if (options.proverNode) { const { startProverNode } = await import('./cmds/start_prover_node.js'); - await startProverNode(options, signalHandlers, services, userLog); + ({ config } = await startProverNode(options, signalHandlers, services, userLog)); } else if (options.pxe) { const { startPXE } = await import('./cmds/start_pxe.js'); - await startPXE(options, signalHandlers, services, userLog); + ({ config } = await startPXE(options, signalHandlers, services, userLog)); } else if (options.archiver) { const { startArchiver } = await import('./cmds/start_archiver.js'); - await startArchiver(options, signalHandlers, services); + ({ config } = await startArchiver(options, signalHandlers, services)); } else if (options.p2pBootstrap) { const { startP2PBootstrap } = await import('./cmds/start_p2p_bootstrap.js'); - await startP2PBootstrap(options, signalHandlers, services, userLog); + ({ config } = await startP2PBootstrap(options, signalHandlers, services, userLog)); } else if (options.proverAgent) { const { startProverAgent } = await import('./cmds/start_prover_agent.js'); await startProverAgent(options, signalHandlers, services, userLog); @@ -102,14 +105,14 @@ export async function aztecStart(options: any, userLog: LogFn, debugLogger: Logg } installSignalHandlers(debugLogger.info, signalHandlers); - + const versions = getVersions(config); if (Object.entries(services).length > 0) { const rpcServer = createNamespacedSafeJsonRpcServer(services, { http200OnError: false, log: debugLogger, - middlewares: [getOtelJsonRpcPropagationMiddleware()], + middlewares: [getOtelJsonRpcPropagationMiddleware(), getVersioningMiddleware(versions)], }); const { port } = await startHttpRpcServer(rpcServer, { port: options.port }); - debugLogger.info(`Aztec Server listening on port ${port}`); + debugLogger.info(`Aztec Server listening on port ${port}`, versions); } } diff --git a/yarn-project/aztec/src/cli/cmds/start_archiver.ts b/yarn-project/aztec/src/cli/cmds/start_archiver.ts index 99a3a180b45..6468f2bd638 100644 --- a/yarn-project/aztec/src/cli/cmds/start_archiver.ts +++ b/yarn-project/aztec/src/cli/cmds/start_archiver.ts @@ -16,12 +16,14 @@ import { getConfigEnvVars as getTelemetryClientConfig, initTelemetryClient } fro import { extractRelevantOptions } from '../util.js'; import { validateL1Config } from '../validation.js'; +export type { ArchiverConfig, DataStoreConfig }; + /** Starts a standalone archiver. */ export async function startArchiver( options: any, signalHandlers: (() => Promise)[], services: NamespacedApiHandlers, -) { +): Promise<{ config: ArchiverConfig & DataStoreConfig }> { const archiverConfig = extractRelevantOptions( options, { @@ -43,5 +45,6 @@ export async function startArchiver( const archiver = await Archiver.createAndSync(archiverConfig, archiverStore, { telemetry, blobSinkClient }, true); services.archiver = [archiver, ArchiverApiSchema]; signalHandlers.push(archiver.stop); - return services; + + return { config: archiverConfig }; } diff --git a/yarn-project/aztec/src/cli/cmds/start_bot.ts b/yarn-project/aztec/src/cli/cmds/start_bot.ts index 4e5af62d1bc..2c6abf0d9f8 100644 --- a/yarn-project/aztec/src/cli/cmds/start_bot.ts +++ b/yarn-project/aztec/src/cli/cmds/start_bot.ts @@ -24,7 +24,7 @@ export async function startBot( let pxe: PXE | undefined; if (options.pxe) { const { addPXE } = await import('./start_pxe.js'); - pxe = await addPXE(options, signalHandlers, services, userLog); + ({ pxe } = await addPXE(options, signalHandlers, services, userLog)); } const telemetry = initTelemetryClient(getTelemetryClientConfig()); diff --git a/yarn-project/aztec/src/cli/cmds/start_node.ts b/yarn-project/aztec/src/cli/cmds/start_node.ts index ddb35e2ab33..b70690af24d 100644 --- a/yarn-project/aztec/src/cli/cmds/start_node.ts +++ b/yarn-project/aztec/src/cli/cmds/start_node.ts @@ -112,7 +112,7 @@ export async function startNode( let pxe: PXE | undefined; if (options.pxe) { const { addPXE } = await import('./start_pxe.js'); - pxe = await addPXE(options, signalHandlers, services, userLog, { node }); + ({ pxe } = await addPXE(options, signalHandlers, services, userLog, { node })); } // Add a txs bot if requested @@ -120,4 +120,6 @@ export async function startNode( const { addBot } = await import('./start_bot.js'); await addBot(options, signalHandlers, services, { pxe, node, telemetry }); } + + return { config: nodeConfig }; } diff --git a/yarn-project/aztec/src/cli/cmds/start_p2p_bootstrap.ts b/yarn-project/aztec/src/cli/cmds/start_p2p_bootstrap.ts index f312b59fa8d..5b7a79e908d 100644 --- a/yarn-project/aztec/src/cli/cmds/start_p2p_bootstrap.ts +++ b/yarn-project/aztec/src/cli/cmds/start_p2p_bootstrap.ts @@ -22,4 +22,5 @@ export async function startP2PBootstrap( signalHandlers.push(() => node.stop()); services.bootstrap = [node, P2PBootstrapApiSchema]; userLog(`P2P bootstrap node started on ${config.udpListenAddress}`); + return { config }; } diff --git a/yarn-project/aztec/src/cli/cmds/start_prover_agent.ts b/yarn-project/aztec/src/cli/cmds/start_prover_agent.ts index 23919f407d0..5c7925ded9e 100644 --- a/yarn-project/aztec/src/cli/cmds/start_prover_agent.ts +++ b/yarn-project/aztec/src/cli/cmds/start_prover_agent.ts @@ -13,6 +13,7 @@ import { getProverNodeAgentConfigFromEnv } from '@aztec/prover-node'; import { initTelemetryClient, telemetryClientConfigMappings } from '@aztec/telemetry-client'; import { extractRelevantOptions } from '../util.js'; +import { getVersions } from '../versioning.js'; export async function startProverAgent( options: any, @@ -38,7 +39,7 @@ export async function startProverAgent( process.exit(1); } - const broker = createProvingJobBrokerClient(config.proverBrokerUrl); + const broker = createProvingJobBrokerClient(config.proverBrokerUrl, getVersions()); const telemetry = initTelemetryClient(extractRelevantOptions(options, telemetryClientConfigMappings, 'tel')); const prover = await buildServerCircuitProver(config, telemetry); diff --git a/yarn-project/aztec/src/cli/cmds/start_prover_broker.ts b/yarn-project/aztec/src/cli/cmds/start_prover_broker.ts index ad53dea8fa2..e49add6359e 100644 --- a/yarn-project/aztec/src/cli/cmds/start_prover_broker.ts +++ b/yarn-project/aztec/src/cli/cmds/start_prover_broker.ts @@ -17,7 +17,7 @@ export async function startProverBroker( signalHandlers: (() => Promise)[], services: NamespacedApiHandlers, userLog: LogFn, -): Promise { +): Promise<{ broker: ProvingJobBroker; config: ProverBrokerConfig }> { if (options.node || options.sequencer || options.pxe || options.p2pBootstrap || options.txe) { userLog(`Starting a prover broker with --node, --sequencer, --pxe, --p2p-bootstrap, or --txe is not supported.`); process.exit(1); @@ -33,5 +33,5 @@ export async function startProverBroker( services.proverBroker = [broker, ProvingJobBrokerSchema]; signalHandlers.push(() => broker.stop()); - return broker; + return { broker, config }; } diff --git a/yarn-project/aztec/src/cli/cmds/start_prover_node.ts b/yarn-project/aztec/src/cli/cmds/start_prover_node.ts index 6264a46ac5f..43d9d04ac1b 100644 --- a/yarn-project/aztec/src/cli/cmds/start_prover_node.ts +++ b/yarn-project/aztec/src/cli/cmds/start_prover_node.ts @@ -15,6 +15,7 @@ import { mnemonicToAccount } from 'viem/accounts'; import { extractRelevantOptions } from '../util.js'; import { validateL1Config } from '../validation.js'; +import { getVersions } from '../versioning.js'; import { startProverBroker } from './start_prover_broker.js'; export async function startProverNode( @@ -68,9 +69,9 @@ export async function startProverNode( let broker: ProvingJobBroker; if (proverConfig.proverBrokerUrl) { - broker = createProvingJobBrokerClient(proverConfig.proverBrokerUrl); + broker = createProvingJobBrokerClient(proverConfig.proverBrokerUrl, getVersions(proverConfig)); } else if (options.proverBroker) { - broker = await startProverBroker(options, signalHandlers, services, userLog); + ({ broker } = await startProverBroker(options, signalHandlers, services, userLog)); } else { userLog(`--prover-broker-url or --prover-broker is required to start a Prover Node`); process.exit(1); @@ -97,4 +98,5 @@ export async function startProverNode( signalHandlers.push(proverNode.stop.bind(proverNode)); await proverNode.start(); + return { config: proverConfig }; } diff --git a/yarn-project/aztec/src/cli/cmds/start_pxe.ts b/yarn-project/aztec/src/cli/cmds/start_pxe.ts index 6254e2ee194..959254e36fd 100644 --- a/yarn-project/aztec/src/cli/cmds/start_pxe.ts +++ b/yarn-project/aztec/src/cli/cmds/start_pxe.ts @@ -12,6 +12,7 @@ import { type LogFn } from '@aztec/foundation/log'; import { AztecAddress, type CliPXEOptions, + type PXEService, type PXEServiceConfig, allPxeConfigMappings, createPXEService, @@ -20,6 +21,9 @@ import { makeTracedFetch } from '@aztec/telemetry-client'; import { L2BasicContractsMap, Network } from '@aztec/types/network'; import { extractRelevantOptions } from '../util.js'; +import { getVersions } from '../versioning.js'; + +export type { PXEServiceConfig, CliPXEOptions }; const contractAddressesUrl = 'http://static.aztec.network'; @@ -28,9 +32,8 @@ export async function startPXE( signalHandlers: (() => Promise)[], services: NamespacedApiHandlers, userLog: LogFn, -) { - await addPXE(options, signalHandlers, services, userLog, {}); - return services; +): Promise<{ pxe: PXEService; config: PXEServiceConfig & CliPXEOptions }> { + return await addPXE(options, signalHandlers, services, userLog, {}); } function isValidNetwork(value: any): value is Network { @@ -51,7 +54,7 @@ export async function addPXE( services: NamespacedApiHandlers, userLog: LogFn, deps: { node?: AztecNode } = {}, -) { +): Promise<{ pxe: PXEService; config: PXEServiceConfig & CliPXEOptions }> { const pxeConfig = extractRelevantOptions(options, allPxeConfigMappings, 'pxe'); let nodeUrl; @@ -77,7 +80,7 @@ export async function addPXE( process.exit(1); } - const node = deps.node ?? createAztecNodeClient(nodeUrl!, makeTracedFetch([1, 2, 3], true)); + const node = deps.node ?? createAztecNodeClient(nodeUrl!, getVersions(pxeConfig), makeTracedFetch([1, 2, 3], true)); const pxe = await createPXEService(node, pxeConfig as PXEServiceConfig); // register basic contracts @@ -120,5 +123,5 @@ export async function addPXE( // Add PXE to services list services.pxe = [pxe, PXESchema]; - return pxe; + return { pxe, config: pxeConfig }; } diff --git a/yarn-project/aztec/src/cli/versioning.ts b/yarn-project/aztec/src/cli/versioning.ts new file mode 100644 index 00000000000..e78da4d594e --- /dev/null +++ b/yarn-project/aztec/src/cli/versioning.ts @@ -0,0 +1,13 @@ +import { type ComponentsVersions, getComponentsVersionsFromConfig } from '@aztec/circuit-types'; +import { type ChainConfig } from '@aztec/circuit-types/config'; +import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vks'; +import { protocolContractTreeRoot } from '@aztec/protocol-contracts'; + +export function getVersions(config?: ChainConfig): Partial { + return config + ? getComponentsVersionsFromConfig(config, protocolContractTreeRoot, getVKTreeRoot()) + : { + l2CircuitsVkTreeRoot: getVKTreeRoot().toString(), + l2ProtocolContractsTreeRoot: protocolContractTreeRoot.toString(), + }; +} diff --git a/yarn-project/aztec/src/sandbox.ts b/yarn-project/aztec/src/sandbox.ts index 9945ae86c04..c1e9d08e854 100644 --- a/yarn-project/aztec/src/sandbox.ts +++ b/yarn-project/aztec/src/sandbox.ts @@ -58,7 +58,7 @@ export async function deployContractsToL1( ...getL1ContractsConfigEnvVars(), // TODO: We should not need to be loading config from env again, caller should handle this ...aztecNodeConfig, l2FeeJuiceAddress: ProtocolContractAddress.FeeJuice, - vkTreeRoot: await getVKTreeRoot(), + vkTreeRoot: getVKTreeRoot(), protocolContractTreeRoot, assumeProvenThrough: opts.assumeProvenThroughBlockNumber, salt: opts.salt, diff --git a/yarn-project/bootstrap.sh b/yarn-project/bootstrap.sh index f0098329a57..0d3e51cf342 100755 --- a/yarn-project/bootstrap.sh +++ b/yarn-project/bootstrap.sh @@ -47,7 +47,7 @@ function build { end-to-end/src/web/{main.js,main.js.LICENSE.txt,*.wasm.gz} \ ivc-integration/src/types/ \ noir-contracts.js/{codegenCache.json,src/} \ - noir-protocol-circuits-types/src/{private_kernel_reset_data.ts,private_kernel_reset_vks.ts,private_kernel_reset_types.ts,client_artifacts_helper.ts,types/} \ + noir-protocol-circuits-types/src/{vk_tree.ts,private_kernel_reset_data.ts,private_kernel_reset_vks.ts,private_kernel_reset_types.ts,client_artifacts_helper.ts,types/} \ pxe/src/config/package_info.ts \ protocol-contracts/src/protocol_contract_data.ts echo diff --git a/yarn-project/bot/package.json b/yarn-project/bot/package.json index 304bac4be34..c14b9bb36ed 100644 --- a/yarn-project/bot/package.json +++ b/yarn-project/bot/package.json @@ -59,6 +59,7 @@ "@aztec/entrypoints": "workspace:^", "@aztec/foundation": "workspace:^", "@aztec/noir-contracts.js": "workspace:^", + "@aztec/noir-protocol-circuits-types": "workspace:^", "@aztec/protocol-contracts": "workspace:^", "@aztec/telemetry-client": "workspace:^", "@aztec/types": "workspace:^", diff --git a/yarn-project/bot/src/config.ts b/yarn-project/bot/src/config.ts index 0600bc99243..d071ad24359 100644 --- a/yarn-project/bot/src/config.ts +++ b/yarn-project/bot/src/config.ts @@ -1,3 +1,4 @@ +import { type ComponentsVersions } from '@aztec/circuit-types'; import { Fr } from '@aztec/circuits.js'; import { type ConfigMappingsType, @@ -8,6 +9,8 @@ import { optionalNumberConfigHelper, } from '@aztec/foundation/config'; import { type ZodFor, schemas } from '@aztec/foundation/schemas'; +import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vks'; +import { protocolContractTreeRoot } from '@aztec/protocol-contracts'; import { z } from 'zod'; @@ -221,3 +224,10 @@ export function getBotConfigFromEnv(): BotConfig { export function getBotDefaultConfig(): BotConfig { return getDefaultConfig(botConfigMappings); } + +export function getVersions(): Partial { + return { + l2ProtocolContractsTreeRoot: protocolContractTreeRoot.toString(), + l2CircuitsVkTreeRoot: getVKTreeRoot().toString(), + }; +} diff --git a/yarn-project/bot/src/factory.ts b/yarn-project/bot/src/factory.ts index e369da715e3..c3c10eb08ed 100644 --- a/yarn-project/bot/src/factory.ts +++ b/yarn-project/bot/src/factory.ts @@ -13,7 +13,7 @@ import { EasyPrivateTokenContract } from '@aztec/noir-contracts.js/EasyPrivateTo import { TokenContract } from '@aztec/noir-contracts.js/Token'; import { makeTracedFetch } from '@aztec/telemetry-client'; -import { type BotConfig, SupportedTokenContracts } from './config.js'; +import { type BotConfig, SupportedTokenContracts, getVersions } from './config.js'; import { getBalances, getPrivateBalance, isStandardTokenContract } from './utils.js'; const MINT_BALANCE = 1e12; @@ -40,7 +40,7 @@ export class BotFactory { return; } this.log.info(`Using remote PXE at ${config.pxeUrl!}`); - this.pxe = createPXEClient(config.pxeUrl!, makeTracedFetch([1, 2, 3], false)); + this.pxe = createPXEClient(config.pxeUrl!, getVersions(), makeTracedFetch([1, 2, 3], false)); } /** diff --git a/yarn-project/bot/src/runner.ts b/yarn-project/bot/src/runner.ts index e2731439d7b..a178d4e2302 100644 --- a/yarn-project/bot/src/runner.ts +++ b/yarn-project/bot/src/runner.ts @@ -3,7 +3,7 @@ import { RunningPromise } from '@aztec/foundation/running-promise'; import { type TelemetryClient, type Traceable, type Tracer, makeTracedFetch, trackSpan } from '@aztec/telemetry-client'; import { Bot } from './bot.js'; -import { type BotConfig } from './config.js'; +import { type BotConfig, getVersions } from './config.js'; import { type BotRunnerApi } from './interface.js'; export class BotRunner implements BotRunnerApi, Traceable { @@ -26,7 +26,8 @@ export class BotRunner implements BotRunnerApi, Traceable { if (!dependencies.node && !config.nodeUrl) { throw new Error(`Missing node URL in config or dependencies`); } - this.node = dependencies.node ?? createAztecNodeClient(config.nodeUrl!, makeTracedFetch([1, 2, 3], true)); + this.node = + dependencies.node ?? createAztecNodeClient(config.nodeUrl!, getVersions(), makeTracedFetch([1, 2, 3], true)); this.runningPromise = new RunningPromise(() => this.#work(), this.log, config.txIntervalSeconds * 1000); } diff --git a/yarn-project/bot/tsconfig.json b/yarn-project/bot/tsconfig.json index fadf21845ae..53946aaa46a 100644 --- a/yarn-project/bot/tsconfig.json +++ b/yarn-project/bot/tsconfig.json @@ -27,6 +27,9 @@ { "path": "../noir-contracts.js" }, + { + "path": "../noir-protocol-circuits-types" + }, { "path": "../protocol-contracts" }, diff --git a/yarn-project/circuit-types/package.json b/yarn-project/circuit-types/package.json index 3a4008fbbdc..b60569aa9bb 100644 --- a/yarn-project/circuit-types/package.json +++ b/yarn-project/circuit-types/package.json @@ -81,6 +81,7 @@ "devDependencies": { "@jest/globals": "^29.5.0", "@types/jest": "^29.5.0", + "@types/koa": "^2.15.0", "@types/lodash.clonedeep": "^4.5.7", "@types/lodash.isequal": "^4.5.6", "@types/lodash.omit": "^4.5.9", diff --git a/yarn-project/circuit-types/src/config.ts b/yarn-project/circuit-types/src/config.ts index 8a4e0291b1a..e5687e47cbe 100644 --- a/yarn-project/circuit-types/src/config.ts +++ b/yarn-project/circuit-types/src/config.ts @@ -1 +1,42 @@ -export { SequencerConfig, AllowedElement, SequencerConfigSchema } from './interfaces/configs.js'; +import { EthAddress } from '@aztec/circuits.js'; +import { l1ContractAddressesMapping } from '@aztec/ethereum'; +import { type ConfigMappingsType, numberConfigHelper } from '@aztec/foundation/config'; + +export { AllowedElement, SequencerConfig, SequencerConfigSchema } from './interfaces/configs.js'; + +export const emptyChainConfig: ChainConfig = { + l1ChainId: 0, + l1Contracts: { rollupAddress: EthAddress.ZERO }, + version: 0, +}; + +export const chainConfigMappings: ConfigMappingsType = { + l1ChainId: { + env: 'L1_CHAIN_ID', + parseEnv: (val: string) => +val, + defaultValue: 31337, + description: 'The chain ID of the ethereum host.', + }, + version: { + env: 'VERSION', + description: 'The version of the rollup.', + ...numberConfigHelper(1), + }, + l1Contracts: { + description: 'The deployed L1 contract addresses', + nested: l1ContractAddressesMapping, + }, +}; + +/** Chain configuration. */ +export type ChainConfig = { + /** The chain id of the ethereum host. */ + l1ChainId: number; + /** The version of the rollup. */ + version: number; + /** The address to the L1 contracts. */ + l1Contracts: { + /** The address to rollup */ + rollupAddress: EthAddress; + }; +}; diff --git a/yarn-project/circuit-types/src/index.ts b/yarn-project/circuit-types/src/index.ts index a6dd1955cf7..aa7bfb3efea 100644 --- a/yarn-project/circuit-types/src/index.ts +++ b/yarn-project/circuit-types/src/index.ts @@ -26,3 +26,4 @@ export * from './in_block.js'; export * from './nullifier_with_block_source.js'; export * from './proving_error.js'; export * from './epoch-helpers/index.js'; +export * from './versioning.js'; diff --git a/yarn-project/circuit-types/src/interfaces/aztec-node.ts b/yarn-project/circuit-types/src/interfaces/aztec-node.ts index 1b5afd8e476..9018ea44418 100644 --- a/yarn-project/circuit-types/src/interfaces/aztec-node.ts +++ b/yarn-project/circuit-types/src/interfaces/aztec-node.ts @@ -49,6 +49,7 @@ import { TxValidationResultSchema, } from '../tx/index.js'; import { TxEffect } from '../tx_effect.js'; +import { type ComponentsVersions, getVersioningResponseHandler } from '../versioning.js'; import { type SequencerConfig, SequencerConfigSchema } from './configs.js'; import { type L2BlockNumber, L2BlockNumberSchema } from './l2_block_number.js'; import { NullifierMembershipWitness } from './nullifier_membership_witness.js'; @@ -601,6 +602,14 @@ export const AztecNodeApiSchema: ApiSchemaFor = { addContractClass: z.function().args(ContractClassPublicSchema).returns(z.void()), }; -export function createAztecNodeClient(url: string, fetch = defaultFetch): AztecNode { - return createSafeJsonRpcClient(url, AztecNodeApiSchema, false, 'node', fetch); +export function createAztecNodeClient( + url: string, + versions: Partial = {}, + fetch = defaultFetch, +): AztecNode { + return createSafeJsonRpcClient(url, AztecNodeApiSchema, { + namespaceMethods: 'node', + fetch, + onResponse: getVersioningResponseHandler(versions), + }); } diff --git a/yarn-project/circuit-types/src/versioning.test.ts b/yarn-project/circuit-types/src/versioning.test.ts new file mode 100644 index 00000000000..5a63fa1acd9 --- /dev/null +++ b/yarn-project/circuit-types/src/versioning.test.ts @@ -0,0 +1,108 @@ +import { EthAddress } from '@aztec/foundation/eth-address'; +import { Fr } from '@aztec/foundation/fields'; +import { createSafeJsonRpcClient } from '@aztec/foundation/json-rpc/client'; +import { type JsonRpcTestContext, createJsonRpcTestSetup } from '@aztec/foundation/json-rpc/test'; +import { type ApiSchemaFor } from '@aztec/foundation/schemas'; + +import { z } from 'zod'; + +import { + type ComponentsVersions, + checkCompressedComponentVersion, + compressComponentVersions, + getVersioningMiddleware, + getVersioningResponseHandler, + validatePartialComponentVersionsMatch, +} from './versioning.js'; + +describe('versioning', () => { + let versions: ComponentsVersions; + + beforeAll(() => { + versions = { + l1ChainId: 1, + l1RollupAddress: EthAddress.random(), + l2ChainVersion: 3, + l2ProtocolContractsTreeRoot: Fr.random().toString(), + l2CircuitsVkTreeRoot: Fr.random().toString(), + }; + }); + + describe('comparing', () => { + it('compresses and checks', () => { + checkCompressedComponentVersion(compressComponentVersions(versions), versions); + }); + + it('throws on mismatch in compressed', () => { + const compressed = compressComponentVersions(versions); + const expected = { ...versions, l1ChainId: 2 }; + expect(() => checkCompressedComponentVersion(compressed, expected)).toThrow(/L1 chain/); + }); + + it('validates partial versions', () => { + const partial = { l1ChainId: 1, l2ChainVersion: 3 }; + validatePartialComponentVersionsMatch(partial, versions); + }); + + it('throws on mismatch for partial versions', () => { + const partial = { l1ChainId: 10, l2ChainVersion: 3 }; + expect(() => validatePartialComponentVersionsMatch(partial, versions)).toThrow(/l1ChainId/); + }); + }); + + describe('json-rpc', () => { + type TestApi = { get: () => Promise }; + const TestApiSchema: ApiSchemaFor = { get: z.function().returns(z.number()) }; + + let context: JsonRpcTestContext; + let versions: Partial; + + beforeAll(async () => { + versions = { + l1ChainId: 1, + l1RollupAddress: EthAddress.random(), + l2ChainVersion: undefined, + l2ProtocolContractsTreeRoot: Fr.random().toString(), + l2CircuitsVkTreeRoot: Fr.random().toString(), + }; + + const handler = { get: () => Promise.resolve(1) }; + context = await createJsonRpcTestSetup( + handler, + TestApiSchema, + { middlewares: [getVersioningMiddleware(versions)] }, + { onResponse: getVersioningResponseHandler(versions) }, + ); + }); + + afterAll(() => { + context.httpServer.close(); + }); + + it('passes versioning headers', async () => { + const result = await context.client.get(); + expect(result).toBe(1); + }); + + it('throws on mismatch', async () => { + const client = createSafeJsonRpcClient(context.url, TestApiSchema, { + onResponse: getVersioningResponseHandler({ ...versions, l1ChainId: 2 }), + }); + await expect(client.get()).rejects.toThrow(/chain/i); + }); + + it('passes if missing on server', async () => { + const client = createSafeJsonRpcClient(context.url, TestApiSchema, { + onResponse: getVersioningResponseHandler({ ...versions, l2ChainVersion: 5 }), + }); + expect(await client.get()).toEqual(1); + }); + + it('passes if missing on client', async () => { + const client = createSafeJsonRpcClient(context.url, TestApiSchema, { + onResponse: getVersioningResponseHandler({ ...versions, l1ChainId: undefined }), + }); + expect(await client.get()).toEqual(1); + }); + }); +}); diff --git a/yarn-project/circuit-types/src/versioning.ts b/yarn-project/circuit-types/src/versioning.ts new file mode 100644 index 00000000000..a4be555a8d1 --- /dev/null +++ b/yarn-project/circuit-types/src/versioning.ts @@ -0,0 +1,152 @@ +import { type EthAddress } from '@aztec/foundation/eth-address'; +import { type Fr } from '@aztec/foundation/fields'; +import { jsonStringify } from '@aztec/foundation/json-rpc'; + +import type Koa from 'koa'; + +import { type ChainConfig } from './config.js'; + +// REFACTOR: This file is not a circuit-type, but at the moment we don't have any other +// package common to all components that we can use for this shared code. + +/** Fields that identify a version of the Aztec protocol. Any mismatch between these fields should signal an incompatibility between nodes. */ +export type ComponentsVersions = { + l1ChainId: number; + // TODO: Consider using governance address instead to support migrations. + // Note that we are using the rollup address as identifier in multiple places + // such as the keystore, we need to change it so we can handle updates. + l1RollupAddress: EthAddress; + l2ChainVersion: number; + l2ProtocolContractsTreeRoot: string; + l2CircuitsVkTreeRoot: string; +}; + +/** Returns components versions from chain config. */ +export function getComponentsVersionsFromConfig( + config: ChainConfig, + l2ProtocolContractsTreeRoot: string | Fr, + l2CircuitsVkTreeRoot: string | Fr, +): ComponentsVersions { + return { + l1ChainId: config.l1ChainId, + l1RollupAddress: config.l1Contracts?.rollupAddress, // This should not be undefined, but sometimes the config lies to us and it is... + l2ChainVersion: config.version, + l2ProtocolContractsTreeRoot: l2ProtocolContractsTreeRoot.toString(), + l2CircuitsVkTreeRoot: l2CircuitsVkTreeRoot.toString(), + }; +} + +/** Returns a compressed string representation of the version (around 32 chars). Used in p2p ENRs. */ +export function compressComponentVersions(versions: ComponentsVersions): string { + if ( + versions.l1RollupAddress === undefined || + versions.l2ProtocolContractsTreeRoot === undefined || + versions.l2CircuitsVkTreeRoot === undefined + ) { + throw new Error(`Component versions are not set: ${jsonStringify(versions)}`); + } + return [ + '00', + versions.l1ChainId, + versions.l1RollupAddress.toString().slice(2, 10), + versions.l2ChainVersion, + versions.l2ProtocolContractsTreeRoot.toString().slice(2, 10), + versions.l2CircuitsVkTreeRoot.toString().slice(2, 10), + ].join('-'); +} + +export class ComponentsVersionsError extends Error { + constructor(key: string, expected: string, value: string) { + super(`Expected component version ${key} to be ${expected} but received ${value}`); + this.name = 'ComponentsVersionsError'; + } +} + +/** Checks if the compressed string matches against the expected versions. Throws on mismatch. */ +export function checkCompressedComponentVersion(compressed: string, expected: ComponentsVersions) { + const [ + versionVersion, + l1ChainId, + l1RollupAddress, + l2ChainVersion, + l2ProtocolContractsTreeRoot, + l2CircuitsVkTreeRoot, + ] = compressed.split('-'); + if (versionVersion !== '00') { + throw new ComponentsVersionsError('version', '00', versionVersion); + } + if (l1ChainId !== expected.l1ChainId.toString()) { + throw new ComponentsVersionsError(`L1 chain ID`, expected.l1ChainId.toString(), l1ChainId); + } + if (l1RollupAddress !== expected.l1RollupAddress.toString().slice(2, 10)) { + throw new ComponentsVersionsError(`L1 address`, expected.l1RollupAddress.toString(), l1RollupAddress); + } + if (l2ChainVersion !== expected.l2ChainVersion.toString()) { + throw new ComponentsVersionsError('L2 chain version', expected.l2ChainVersion.toString(), l2ChainVersion); + } + if (l2ProtocolContractsTreeRoot !== expected.l2ProtocolContractsTreeRoot.toString().slice(2, 10)) { + throw new ComponentsVersionsError( + `L2 protocol contracts vk tree root`, + expected.l2ProtocolContractsTreeRoot.toString(), + l2ProtocolContractsTreeRoot, + ); + } + if (l2CircuitsVkTreeRoot !== expected.l2CircuitsVkTreeRoot.toString().slice(2, 10)) { + throw new ComponentsVersionsError( + 'L2 circuits vk tree root', + expected.l2CircuitsVkTreeRoot.toString(), + l2CircuitsVkTreeRoot, + ); + } +} + +/** Checks that two component versions match. Undefined fields are ignored. */ +export function validatePartialComponentVersionsMatch( + expected: Partial, + actual: Partial, +) { + for (const key of [ + 'l1RollupAddress', + 'l2ProtocolContractsTreeRoot', + 'l2CircuitsVkTreeRoot', + 'l1ChainId', + 'l2ChainVersion', + ] as const) { + const actualValue = actual[key]; + const expectedValue = expected[key]; + if (expectedValue !== undefined && actualValue !== undefined) { + if (typeof actualValue === 'object' ? !actualValue.equals(expectedValue as any) : actualValue !== expectedValue) { + throw new Error(`Expected ${key} to be ${expectedValue} but received ${actualValue}`); + } + } + } +} + +/** Returns a Koa middleware that injects the versioning info as headers. */ +export function getVersioningMiddleware(versions: Partial) { + return async (ctx: Koa.Context, next: () => Promise) => { + await next(); + for (const key in versions) { + const value = versions[key as keyof ComponentsVersions]; + if (value !== undefined) { + ctx.set(`x-aztec-${key}`, value.toString()); + } + } + }; +} + +/** Returns a json rpc client handler that rejects responses with mismatching versions. */ +export function getVersioningResponseHandler(versions: Partial) { + return ({ headers }: { headers: { get: (header: string) => string | null | undefined } }) => { + for (const key in versions) { + const value = versions[key as keyof ComponentsVersions]; + if (value !== undefined) { + const headerValue = headers.get(`x-aztec-${key}`); + if (headerValue !== undefined && headerValue !== null && headerValue !== value.toString()) { + throw new ComponentsVersionsError(key, value.toString(), headerValue); + } + } + } + return Promise.resolve(); + }; +} diff --git a/yarn-project/cli/src/cmds/infrastructure/setup_protocol_contract.ts b/yarn-project/cli/src/cmds/infrastructure/setup_protocol_contract.ts index a7473487d31..35594202613 100644 --- a/yarn-project/cli/src/cmds/infrastructure/setup_protocol_contract.ts +++ b/yarn-project/cli/src/cmds/infrastructure/setup_protocol_contract.ts @@ -21,7 +21,7 @@ export async function setupProtocolContracts( }; log('setupProtocolContracts: Wait options' + jsonStringify(waitOpts)); log('setupProtocolContracts: Creating PXE client...'); - const pxe = createPXEClient(rpcUrl, makeFetch([1, 1, 1, 1, 1], false)); + const pxe = createPXEClient(rpcUrl, {}, makeFetch([1, 1, 1, 1, 1], false)); const wallet = new SignerlessWallet(pxe, new DefaultMultiCallEntrypoint(l1ChainId, 1)); log('setupProtocolContracts: Getting fee juice portal address...'); diff --git a/yarn-project/cli/src/cmds/l1/advance_epoch.ts b/yarn-project/cli/src/cmds/l1/advance_epoch.ts index 75d838a77cb..2cd4e01dea3 100644 --- a/yarn-project/cli/src/cmds/l1/advance_epoch.ts +++ b/yarn-project/cli/src/cmds/l1/advance_epoch.ts @@ -2,7 +2,7 @@ import { CheatCodes, createPXEClient, makeFetch } from '@aztec/aztec.js'; import { type LogFn } from '@aztec/foundation/log'; export async function advanceEpoch(l1RpcUrl: string, rpcUrl: string, log: LogFn) { - const pxe = createPXEClient(rpcUrl, makeFetch([], true)); + const pxe = createPXEClient(rpcUrl, {}, makeFetch([], true)); const rollupAddress = await pxe.getNodeInfo().then(i => i.l1ContractAddresses.rollupAddress); const cheat = CheatCodes.createRollup(l1RpcUrl, { rollupAddress }); diff --git a/yarn-project/cli/src/cmds/l1/assume_proven_through.ts b/yarn-project/cli/src/cmds/l1/assume_proven_through.ts index 23102deb8d1..ab7afe84f49 100644 --- a/yarn-project/cli/src/cmds/l1/assume_proven_through.ts +++ b/yarn-project/cli/src/cmds/l1/assume_proven_through.ts @@ -16,7 +16,7 @@ export async function assumeProvenThrough( const chain = createEthereumChain(l1RpcUrl, chainId); const { walletClient } = createL1Clients(chain.rpcUrl, privateKey ?? mnemonic, chain.chainInfo); - const pxe = createPXEClient(rpcUrl, makeFetch([], true)); + const pxe = createPXEClient(rpcUrl, {}, makeFetch([], true)); const rollupAddress = await pxe.getNodeInfo().then(i => i.l1ContractAddresses.rollupAddress); const blockNumber = blockNumberOrLatest ?? (await pxe.getBlockNumber()); diff --git a/yarn-project/cli/src/utils/aztec.ts b/yarn-project/cli/src/utils/aztec.ts index 9635839992f..44ce022bb5a 100644 --- a/yarn-project/cli/src/utils/aztec.ts +++ b/yarn-project/cli/src/utils/aztec.ts @@ -67,7 +67,7 @@ export async function deployAztecContracts( return await deployL1Contracts(chain.rpcUrl, account, chain.chainInfo, debugLogger, { l2FeeJuiceAddress: ProtocolContractAddress.FeeJuice, - vkTreeRoot: await getVKTreeRoot(), + vkTreeRoot: getVKTreeRoot(), protocolContractTreeRoot, salt, initialValidators, diff --git a/yarn-project/end-to-end/src/bench/utils.ts b/yarn-project/end-to-end/src/bench/utils.ts index a1685128045..69ad995a7e3 100644 --- a/yarn-project/end-to-end/src/bench/utils.ts +++ b/yarn-project/end-to-end/src/bench/utils.ts @@ -177,12 +177,15 @@ export async function createNewPXE( startingBlock: number = INITIAL_L2_BLOCK_NUM, ): Promise { const l1Contracts = await node.getL1ContractAddresses(); + const { l1ChainId, protocolVersion } = await node.getNodeInfo(); const pxeConfig = { l2StartingBlock: startingBlock, l2BlockPollingIntervalMS: 100, dataDirectory: undefined, dataStoreMapSizeKB: 1024 * 1024, l1Contracts, + l1ChainId, + version: protocolVersion, } as PXEServiceConfig; const pxe = await createPXEService(node, pxeConfig); await pxe.registerContract(contract); diff --git a/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts b/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts index 5745702fb55..fea5ee358f3 100644 --- a/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts +++ b/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts @@ -251,12 +251,12 @@ describe('L1Publisher integration', () => { await worldStateSynchronizer.stop(); }); - const makeProcessedTx = async (seed = 0x1): Promise => + const makeProcessedTx = (seed = 0x1): Promise => makeBloatedProcessedTx({ header: prevHeader, chainId: fr(chainId), version: fr(config.version), - vkTreeRoot: await getVKTreeRoot(), + vkTreeRoot: getVKTreeRoot(), gasSettings: GasSettings.default({ maxFeesPerGas: baseFee }), protocolContractTreeRoot, seed, diff --git a/yarn-project/end-to-end/src/e2e_deploy_contract/deploy_method.test.ts b/yarn-project/end-to-end/src/e2e_deploy_contract/deploy_method.test.ts index 07b9af169ad..3ad4ee7db15 100644 --- a/yarn-project/end-to-end/src/e2e_deploy_contract/deploy_method.test.ts +++ b/yarn-project/end-to-end/src/e2e_deploy_contract/deploy_method.test.ts @@ -149,7 +149,7 @@ describe('e2e_deploy_contract deploy method', () => { if (!PXE_URL) { return; } - const pxeClient = createPXEClient(PXE_URL, makeFetch([1, 2, 3], false)); + const pxeClient = createPXEClient(PXE_URL, {}, makeFetch([1, 2, 3], false)); const [wallet] = await getDeployedTestAccountsWallets(pxeClient); await expect( StatefulTestContract.deployWithOpts({ wallet, method: 'wrong_constructor' }).send().deployed(), diff --git a/yarn-project/end-to-end/src/fixtures/setup_l1_contracts.ts b/yarn-project/end-to-end/src/fixtures/setup_l1_contracts.ts index e918fae40a3..0a90dbcc2e1 100644 --- a/yarn-project/end-to-end/src/fixtures/setup_l1_contracts.ts +++ b/yarn-project/end-to-end/src/fixtures/setup_l1_contracts.ts @@ -16,7 +16,7 @@ export const setupL1Contracts = async ( ) => { const l1Data = await deployL1Contracts(l1RpcUrl, account, foundry, logger, { l2FeeJuiceAddress: ProtocolContractAddress.FeeJuice, - vkTreeRoot: await getVKTreeRoot(), + vkTreeRoot: getVKTreeRoot(), protocolContractTreeRoot, salt: undefined, ...args, diff --git a/yarn-project/end-to-end/src/fixtures/utils.ts b/yarn-project/end-to-end/src/fixtures/utils.ts index 4331ad70de2..e6a6a32c968 100644 --- a/yarn-project/end-to-end/src/fixtures/utils.ts +++ b/yarn-project/end-to-end/src/fixtures/utils.ts @@ -119,7 +119,7 @@ export const setupL1Contracts = async ( ) => { const l1Data = await deployL1Contracts(l1RpcUrl, account, chain, logger, { l2FeeJuiceAddress: ProtocolContractAddress.FeeJuice, - vkTreeRoot: await getVKTreeRoot(), + vkTreeRoot: getVKTreeRoot(), protocolContractTreeRoot, salt: args.salt, initialValidators: args.initialValidators, @@ -204,7 +204,7 @@ async function setupWithRemoteEnvironment( logger.verbose(`Creating Aztec Node client to remote host ${aztecNodeUrl}`); const aztecNode = createAztecNodeClient(aztecNodeUrl); logger.verbose(`Creating PXE client to remote host ${PXE_URL}`); - const pxeClient = createPXEClient(PXE_URL, makeFetch([1, 2, 3], true)); + const pxeClient = createPXEClient(PXE_URL, {}, makeFetch([1, 2, 3], true)); await waitForPXE(pxeClient, logger); logger.verbose('JSON RPC client connected to PXE'); logger.verbose(`Retrieving contract addresses from ${PXE_URL}`); diff --git a/yarn-project/foundation/src/config/env_var.ts b/yarn-project/foundation/src/config/env_var.ts index 8467b9d2431..366bf694a08 100644 --- a/yarn-project/foundation/src/config/env_var.ts +++ b/yarn-project/foundation/src/config/env_var.ts @@ -78,6 +78,7 @@ export type EnvVar = | 'OUTBOX_CONTRACT_ADDRESS' | 'P2P_BLOCK_CHECK_INTERVAL_MS' | 'P2P_BLOCK_REQUEST_BATCH_SIZE' + | 'P2P_BOOTSTRAP_NODE_ENR_VERSION_CHECK' | 'P2P_ENABLED' | 'P2P_GOSSIPSUB_D' | 'P2P_GOSSIPSUB_DHI' diff --git a/yarn-project/foundation/src/json-rpc/client/fetch.ts b/yarn-project/foundation/src/json-rpc/client/fetch.ts index fa02103a121..78f8045029f 100644 --- a/yarn-project/foundation/src/json-rpc/client/fetch.ts +++ b/yarn-project/foundation/src/json-rpc/client/fetch.ts @@ -23,7 +23,7 @@ export async function defaultFetch( useApiEndpoints: boolean, extraHeaders: Record = {}, noRetry = false, -) { +): Promise<{ response: any; headers: { get: (header: string) => string | null | undefined } }> { log.debug(format(`JsonRpcClient.fetch`, host, rpcMethod, '->', body)); let resp: Response; try { @@ -64,7 +64,7 @@ export async function defaultFetch( } } - return responseJson; + return { response: responseJson, headers: resp.headers }; } /** diff --git a/yarn-project/foundation/src/json-rpc/client/safe_json_rpc_client.ts b/yarn-project/foundation/src/json-rpc/client/safe_json_rpc_client.ts index 471fd9f22ed..7332df1523f 100644 --- a/yarn-project/foundation/src/json-rpc/client/safe_json_rpc_client.ts +++ b/yarn-project/foundation/src/json-rpc/client/safe_json_rpc_client.ts @@ -1,9 +1,20 @@ import { format } from 'util'; -import { createLogger } from '../../log/pino-logger.js'; +import { type Logger, createLogger } from '../../log/pino-logger.js'; import { type ApiSchema, type ApiSchemaFor, schemaHasMethod } from '../../schemas/api.js'; import { defaultFetch } from './fetch.js'; +export type SafeJsonRpcClientOptions = { + useApiEndpoints?: boolean; + namespaceMethods?: string | false; + fetch?: typeof defaultFetch; + log?: Logger; + onResponse?: (res: { + response: any; + headers: { get: (header: string) => string | null | undefined }; + }) => Promise; +}; + /** * Creates a Proxy object that delegates over RPC and validates outputs against a given schema. * The server is expected to be a JsonRpcServer. @@ -16,11 +27,12 @@ import { defaultFetch } from './fetch.js'; export function createSafeJsonRpcClient( host: string, schema: ApiSchemaFor, - useApiEndpoints: boolean = false, - namespaceMethods?: string | false, - fetch = defaultFetch, - log = createLogger('json-rpc:client'), + config: SafeJsonRpcClientOptions = {}, ): T { + const fetch = config.fetch ?? defaultFetch; + const log = config.log ?? createLogger('json-rpc:client'); + const { useApiEndpoints = false, namespaceMethods = false } = config; + let id = 0; const request = async (methodName: string, params: any[]): Promise => { if (!schemaHasMethod(schema, methodName)) { @@ -30,17 +42,20 @@ export function createSafeJsonRpcClient( const body = { jsonrpc: '2.0', id: id++, method, params }; log.debug(format(`request`, method, params)); - const res = await fetch(host, method, body, useApiEndpoints); - log.debug(format(`result`, method, res)); + const { response, headers } = await fetch(host, method, body, useApiEndpoints); + log.debug(format(`result`, method, response)); - if (res.error) { - throw res.error; + if (config.onResponse) { + await config.onResponse({ response, headers }); + } + if (response.error) { + throw response.error; } // TODO(palla/schemas): Find a better way to handle null responses (JSON.stringify(null) is string "null"). - if ([null, undefined, 'null', 'undefined'].includes(res.result)) { + if ([null, undefined, 'null', 'undefined'].includes(response.result)) { return; } - return (schema as ApiSchema)[methodName].returnType().parseAsync(res.result); + return (schema as ApiSchema)[methodName].returnType().parseAsync(response.result); }; const proxy: any = {}; diff --git a/yarn-project/foundation/src/json-rpc/test/integration.test.ts b/yarn-project/foundation/src/json-rpc/test/integration.test.ts index d1611d0acde..91aee21bf63 100644 --- a/yarn-project/foundation/src/json-rpc/test/integration.test.ts +++ b/yarn-project/foundation/src/json-rpc/test/integration.test.ts @@ -142,8 +142,8 @@ describe('JsonRpc integration', () => { httpServer = await startHttpRpcServer(server, { host: '127.0.0.1' }); url = `http://127.0.0.1:${httpServer.port}`; - lettersClient = createSafeJsonRpcClient(url, TestStateSchema, false, 'letters'); - numbersClient = createSafeJsonRpcClient(url, TestStateSchema, false, 'numbers'); + lettersClient = createSafeJsonRpcClient(url, TestStateSchema, { namespaceMethods: 'letters' }); + numbersClient = createSafeJsonRpcClient(url, TestStateSchema, { namespaceMethods: 'numbers' }); }); it('calls correct namespace', async () => { @@ -157,7 +157,7 @@ describe('JsonRpc integration', () => { }); it('fails if calls without namespace', async () => { - const client = createSafeJsonRpcClient(url, TestStateSchema, false); + const client = createSafeJsonRpcClient(url, TestStateSchema); await expect(() => client.getNote(1)).rejects.toThrow('Method not found: getNote'); }); }); diff --git a/yarn-project/foundation/src/json-rpc/test/integration.ts b/yarn-project/foundation/src/json-rpc/test/integration.ts index ac7e6548a77..10775154afa 100644 --- a/yarn-project/foundation/src/json-rpc/test/integration.ts +++ b/yarn-project/foundation/src/json-rpc/test/integration.ts @@ -2,23 +2,34 @@ import type http from 'http'; import { type ApiSchemaFor } from '../../schemas/api.js'; import { makeFetch } from '../client/fetch.js'; -import { createSafeJsonRpcClient } from '../client/safe_json_rpc_client.js'; -import { startHttpRpcServer } from '../server/safe_json_rpc_server.js'; -import { type SafeJsonRpcServer, createSafeJsonRpcServer } from '../server/safe_json_rpc_server.js'; +import { type SafeJsonRpcClientOptions, createSafeJsonRpcClient } from '../client/safe_json_rpc_client.js'; +import { + type SafeJsonRpcServer, + type SafeJsonRpcServerOptions, + createSafeJsonRpcServer, + startHttpRpcServer, +} from '../server/safe_json_rpc_server.js'; export type JsonRpcTestContext = { server: SafeJsonRpcServer; client: T; httpServer: http.Server & { port: number }; + url: string; }; export async function createJsonRpcTestSetup( handler: T, schema: ApiSchemaFor, + serverOptions: Partial = {}, + clientOptions: SafeJsonRpcClientOptions = {}, ): Promise> { - const server = createSafeJsonRpcServer(handler, schema); + const server = createSafeJsonRpcServer(handler, schema, serverOptions); const httpServer = await startHttpRpcServer(server, { host: '127.0.0.1' }); const noRetryFetch = makeFetch([], true); - const client = createSafeJsonRpcClient(`http://127.0.0.1:${httpServer.port}`, schema, false, false, noRetryFetch); - return { server, client, httpServer }; + const url = `http://127.0.0.1:${httpServer.port}`; + const client = createSafeJsonRpcClient(url, schema, { + fetch: noRetryFetch, + ...clientOptions, + }); + return { server, client, httpServer, url }; } diff --git a/yarn-project/l1-artifacts/scripts/generate-artifacts.sh b/yarn-project/l1-artifacts/scripts/generate-artifacts.sh index 802a41ace83..66ea40475ee 100755 --- a/yarn-project/l1-artifacts/scripts/generate-artifacts.sh +++ b/yarn-project/l1-artifacts/scripts/generate-artifacts.sh @@ -68,7 +68,13 @@ echo "// Auto-generated module" >"generated/index.ts" # Add Errors export to index.ts echo "export * from './ErrorsAbi.js';" >>"generated/index.ts" +# Collect all compressed abis +abis="" + for contract_name in "${contracts[@]}"; do + # Append compressed abi to abis collection + abis="$abis:$(jq -c '.abi' "../../l1-contracts/out/${contract_name}.sol/${contract_name}.json")" + # Generate Abi.ts ( echo "/**" @@ -122,4 +128,9 @@ done # Update index.ts exports echo "export * from './RollupStorage.js';" >>"generated/index.ts" -echo "Successfully generated TS artifacts!" +# Write abis hash. Consider excluding some contracts from this hash if +# we don't want to consider them as breaking for the interfaces. +echo "export const AbisChecksum = \"$(echo -n "$abis" | sha256sum | cut -d' ' -f1)\";" >"generated/checksum.ts" +echo "export * from './checksum.js';" >>"generated/index.ts" + +echo "Successfully generated TS artifacts" diff --git a/yarn-project/noir-protocol-circuits-types/package.json b/yarn-project/noir-protocol-circuits-types/package.json index 0485a535db6..bb1ac7151fb 100644 --- a/yarn-project/noir-protocol-circuits-types/package.json +++ b/yarn-project/noir-protocol-circuits-types/package.json @@ -21,10 +21,11 @@ "formatting": "run -T prettier --check ./src && run -T eslint ./src", "formatting:fix": "run -T eslint --fix ./src && run -T prettier -w ./src", "formatting:fix:types": "NODE_OPTIONS='--max-old-space-size=8096' run -T eslint --fix ./src/types && run -T prettier -w ./src/types", - "generate": "yarn generate:copy-artifacts && yarn generate:vk-hashes && yarn generate:noir-circuits && yarn generate:reset-data && yarn generate:client-artifacts-helper", + "generate": "yarn generate:copy-artifacts && yarn generate:vk-hashes && yarn generate:noir-circuits && yarn generate:reset-data && yarn generate:client-artifacts-helper && yarn generate:vk-tree", "generate:copy-artifacts": "mkdir -p ./artifacts && cp -r ../../noir-projects/noir-protocol-circuits/target/* ./artifacts && node --no-warnings --loader ts-node/esm src/scripts/generate_declaration_files.ts ", "generate:cleanup-artifacts": "node --no-warnings --loader ts-node/esm src/scripts/cleanup_artifacts.ts", "generate:vk-hashes": "node --no-warnings --loader ts-node/esm src/scripts/generate_vk_hashes.ts", + "generate:vk-tree": "node --no-warnings --loader ts-node/esm src/scripts/generate_vk_tree.ts && run -T prettier -w ./src/vk_tree.ts", "generate:noir-circuits": "node --no-warnings --loader ts-node/esm src/scripts/generate_ts_from_abi.ts && run -T prettier -w ./src/types", "generate:reset-data": "node --no-warnings --loader ts-node/esm src/scripts/generate_private_kernel_reset_data.ts && run -T prettier -w src/private_kernel_reset_*.ts", "generate:client-artifacts-helper": "node --no-warnings --loader ts-node/esm src/scripts/generate_client_artifacts_helper.ts && run -T prettier -w src/client_artifacts_helper.ts", diff --git a/yarn-project/noir-protocol-circuits-types/src/artifacts/vks.ts b/yarn-project/noir-protocol-circuits-types/src/artifacts/vks.ts new file mode 100644 index 00000000000..3b972f6440b --- /dev/null +++ b/yarn-project/noir-protocol-circuits-types/src/artifacts/vks.ts @@ -0,0 +1,83 @@ +import { + BASE_PARITY_INDEX, + BLOCK_MERGE_ROLLUP_INDEX, + BLOCK_ROOT_ROLLUP_EMPTY_INDEX, + BLOCK_ROOT_ROLLUP_INDEX, + BLOCK_ROOT_ROLLUP_SINGLE_TX_INDEX, + MERGE_ROLLUP_INDEX, + PRIVATE_BASE_ROLLUP_VK_INDEX, + PRIVATE_KERNEL_INIT_INDEX, + PRIVATE_KERNEL_INNER_INDEX, + PRIVATE_KERNEL_TAIL_INDEX, + PRIVATE_KERNEL_TAIL_TO_PUBLIC_INDEX, + PUBLIC_BASE_ROLLUP_VK_INDEX, + ROOT_PARITY_INDEX, + ROOT_ROLLUP_INDEX, + type VerificationKeyData, +} from '@aztec/circuits.js'; + +import BaseParityVkJson from '../../artifacts/keys/parity_base.vk.data.json' assert { type: 'json' }; +import RootParityVkJson from '../../artifacts/keys/parity_root.vk.data.json' assert { type: 'json' }; +import PrivateKernelInitVkJson from '../../artifacts/keys/private_kernel_init.vk.data.json' assert { type: 'json' }; +import PrivateKernelInnerVkJson from '../../artifacts/keys/private_kernel_inner.vk.data.json' assert { type: 'json' }; +import PrivateKernelTailVkJson from '../../artifacts/keys/private_kernel_tail.vk.data.json' assert { type: 'json' }; +import PrivateKernelTailToPublicVkJson from '../../artifacts/keys/private_kernel_tail_to_public.vk.data.json' assert { type: 'json' }; +import PrivateBaseRollupVkJson from '../../artifacts/keys/rollup_base_private.vk.data.json' assert { type: 'json' }; +import PublicBaseRollupVkJson from '../../artifacts/keys/rollup_base_public.vk.data.json' assert { type: 'json' }; +import BlockMergeRollupVkJson from '../../artifacts/keys/rollup_block_merge.vk.data.json' assert { type: 'json' }; +import BlockRootRollupVkJson from '../../artifacts/keys/rollup_block_root.vk.data.json' assert { type: 'json' }; +import EmptyBlockRootRollupVkJson from '../../artifacts/keys/rollup_block_root_empty.vk.data.json' assert { type: 'json' }; +import SingleTxBlockRootRollupVkJson from '../../artifacts/keys/rollup_block_root_single_tx.vk.data.json' assert { type: 'json' }; +import MergeRollupVkJson from '../../artifacts/keys/rollup_merge.vk.data.json' assert { type: 'json' }; +import RootRollupVkJson from '../../artifacts/keys/rollup_root.vk.data.json' assert { type: 'json' }; +import TubeVkJson from '../../artifacts/keys/tube.vk.data.json' assert { type: 'json' }; +import { PrivateKernelResetVkIndexes, PrivateKernelResetVks } from '../private_kernel_reset_vks.js'; +import { keyJsonToVKData } from '../utils/vk_json.js'; +import { type ClientProtocolArtifact, type ProtocolArtifact, type ServerProtocolArtifact } from './types.js'; + +// TODO Include this in the normal maps when the tube is implemented in noir +export const TubeVk = keyJsonToVKData(TubeVkJson); + +export const ServerCircuitVks: Record = { + BaseParityArtifact: keyJsonToVKData(BaseParityVkJson), + RootParityArtifact: keyJsonToVKData(RootParityVkJson), + PrivateBaseRollupArtifact: keyJsonToVKData(PrivateBaseRollupVkJson), + PublicBaseRollupArtifact: keyJsonToVKData(PublicBaseRollupVkJson), + MergeRollupArtifact: keyJsonToVKData(MergeRollupVkJson), + BlockRootRollupArtifact: keyJsonToVKData(BlockRootRollupVkJson), + SingleTxBlockRootRollupArtifact: keyJsonToVKData(SingleTxBlockRootRollupVkJson), + EmptyBlockRootRollupArtifact: keyJsonToVKData(EmptyBlockRootRollupVkJson), + BlockMergeRollupArtifact: keyJsonToVKData(BlockMergeRollupVkJson), + RootRollupArtifact: keyJsonToVKData(RootRollupVkJson), +}; + +export const ClientCircuitVks: Record = { + PrivateKernelInitArtifact: keyJsonToVKData(PrivateKernelInitVkJson), + PrivateKernelInnerArtifact: keyJsonToVKData(PrivateKernelInnerVkJson), + PrivateKernelTailArtifact: keyJsonToVKData(PrivateKernelTailVkJson), + PrivateKernelTailToPublicArtifact: keyJsonToVKData(PrivateKernelTailToPublicVkJson), + ...PrivateKernelResetVks, +}; + +export const ProtocolCircuitVks: Record = { + ...ClientCircuitVks, + ...ServerCircuitVks, +}; + +export const ProtocolCircuitVkIndexes: Record = { + PrivateKernelInitArtifact: PRIVATE_KERNEL_INIT_INDEX, + PrivateKernelInnerArtifact: PRIVATE_KERNEL_INNER_INDEX, + PrivateKernelTailArtifact: PRIVATE_KERNEL_TAIL_INDEX, + PrivateKernelTailToPublicArtifact: PRIVATE_KERNEL_TAIL_TO_PUBLIC_INDEX, + BaseParityArtifact: BASE_PARITY_INDEX, + RootParityArtifact: ROOT_PARITY_INDEX, + PrivateBaseRollupArtifact: PRIVATE_BASE_ROLLUP_VK_INDEX, + PublicBaseRollupArtifact: PUBLIC_BASE_ROLLUP_VK_INDEX, + MergeRollupArtifact: MERGE_ROLLUP_INDEX, + BlockRootRollupArtifact: BLOCK_ROOT_ROLLUP_INDEX, + SingleTxBlockRootRollupArtifact: BLOCK_ROOT_ROLLUP_SINGLE_TX_INDEX, + EmptyBlockRootRollupArtifact: BLOCK_ROOT_ROLLUP_EMPTY_INDEX, + BlockMergeRollupArtifact: BLOCK_MERGE_ROLLUP_INDEX, + RootRollupArtifact: ROOT_ROLLUP_INDEX, + ...PrivateKernelResetVkIndexes, +}; diff --git a/yarn-project/noir-protocol-circuits-types/src/entrypoint/vks.ts b/yarn-project/noir-protocol-circuits-types/src/entrypoint/vks.ts index f2faf209aa8..c010b4efea5 100644 --- a/yarn-project/noir-protocol-circuits-types/src/entrypoint/vks.ts +++ b/yarn-project/noir-protocol-circuits-types/src/entrypoint/vks.ts @@ -1,126 +1,19 @@ -import { - BASE_PARITY_INDEX, - BLOCK_MERGE_ROLLUP_INDEX, - BLOCK_ROOT_ROLLUP_EMPTY_INDEX, - BLOCK_ROOT_ROLLUP_INDEX, - BLOCK_ROOT_ROLLUP_SINGLE_TX_INDEX, - Fr, - MERGE_ROLLUP_INDEX, - type MerkleTree, - MerkleTreeCalculator, - PRIVATE_BASE_ROLLUP_VK_INDEX, - PRIVATE_KERNEL_INIT_INDEX, - PRIVATE_KERNEL_INNER_INDEX, - PRIVATE_KERNEL_TAIL_INDEX, - PRIVATE_KERNEL_TAIL_TO_PUBLIC_INDEX, - PUBLIC_BASE_ROLLUP_VK_INDEX, - ROOT_PARITY_INDEX, - ROOT_ROLLUP_INDEX, - TUBE_VK_INDEX, - VK_TREE_HEIGHT, - VerificationKeyAsFields, - VerificationKeyData, -} from '@aztec/circuits.js'; -import { poseidon2Hash } from '@aztec/foundation/crypto'; +import { Fr, VK_TREE_HEIGHT, VerificationKeyAsFields, VerificationKeyData } from '@aztec/circuits.js'; import { assertLength } from '@aztec/foundation/serialize'; -import BaseParityVkJson from '../../artifacts/keys/parity_base.vk.data.json' assert { type: 'json' }; -import RootParityVkJson from '../../artifacts/keys/parity_root.vk.data.json' assert { type: 'json' }; -import PrivateKernelInitVkJson from '../../artifacts/keys/private_kernel_init.vk.data.json' assert { type: 'json' }; -import PrivateKernelInnerVkJson from '../../artifacts/keys/private_kernel_inner.vk.data.json' assert { type: 'json' }; -import PrivateKernelTailVkJson from '../../artifacts/keys/private_kernel_tail.vk.data.json' assert { type: 'json' }; -import PrivateKernelTailToPublicVkJson from '../../artifacts/keys/private_kernel_tail_to_public.vk.data.json' assert { type: 'json' }; -import PrivateBaseRollupVkJson from '../../artifacts/keys/rollup_base_private.vk.data.json' assert { type: 'json' }; -import PublicBaseRollupVkJson from '../../artifacts/keys/rollup_base_public.vk.data.json' assert { type: 'json' }; -import BlockMergeRollupVkJson from '../../artifacts/keys/rollup_block_merge.vk.data.json' assert { type: 'json' }; -import BlockRootRollupVkJson from '../../artifacts/keys/rollup_block_root.vk.data.json' assert { type: 'json' }; -import EmptyBlockRootRollupVkJson from '../../artifacts/keys/rollup_block_root_empty.vk.data.json' assert { type: 'json' }; -import SingleTxBlockRootRollupVkJson from '../../artifacts/keys/rollup_block_root_single_tx.vk.data.json' assert { type: 'json' }; -import MergeRollupVkJson from '../../artifacts/keys/rollup_merge.vk.data.json' assert { type: 'json' }; -import RootRollupVkJson from '../../artifacts/keys/rollup_root.vk.data.json' assert { type: 'json' }; -import TubeVkJson from '../../artifacts/keys/tube.vk.data.json' assert { type: 'json' }; -import { type ClientProtocolArtifact, type ProtocolArtifact, type ServerProtocolArtifact } from '../artifacts/types.js'; -import { PrivateKernelResetVkIndexes, PrivateKernelResetVks } from '../private_kernel_reset_vks.js'; -import { keyJsonToVKData } from '../utils/vk_json.js'; +import { vkTree } from '../vk_tree.js'; -// TODO Include this in the normal maps when the tube is implemented in noir -export const TubeVk = keyJsonToVKData(TubeVkJson); +export * from '../artifacts/vks.js'; -export const ServerCircuitVks: Record = { - BaseParityArtifact: keyJsonToVKData(BaseParityVkJson), - RootParityArtifact: keyJsonToVKData(RootParityVkJson), - PrivateBaseRollupArtifact: keyJsonToVKData(PrivateBaseRollupVkJson), - PublicBaseRollupArtifact: keyJsonToVKData(PublicBaseRollupVkJson), - MergeRollupArtifact: keyJsonToVKData(MergeRollupVkJson), - BlockRootRollupArtifact: keyJsonToVKData(BlockRootRollupVkJson), - SingleTxBlockRootRollupArtifact: keyJsonToVKData(SingleTxBlockRootRollupVkJson), - EmptyBlockRootRollupArtifact: keyJsonToVKData(EmptyBlockRootRollupVkJson), - BlockMergeRollupArtifact: keyJsonToVKData(BlockMergeRollupVkJson), - RootRollupArtifact: keyJsonToVKData(RootRollupVkJson), -}; - -export const ClientCircuitVks: Record = { - PrivateKernelInitArtifact: keyJsonToVKData(PrivateKernelInitVkJson), - PrivateKernelInnerArtifact: keyJsonToVKData(PrivateKernelInnerVkJson), - PrivateKernelTailArtifact: keyJsonToVKData(PrivateKernelTailVkJson), - PrivateKernelTailToPublicArtifact: keyJsonToVKData(PrivateKernelTailToPublicVkJson), - ...PrivateKernelResetVks, -}; - -export const ProtocolCircuitVks: Record = { - ...ClientCircuitVks, - ...ServerCircuitVks, -}; - -export const ProtocolCircuitVkIndexes: Record = { - PrivateKernelInitArtifact: PRIVATE_KERNEL_INIT_INDEX, - PrivateKernelInnerArtifact: PRIVATE_KERNEL_INNER_INDEX, - PrivateKernelTailArtifact: PRIVATE_KERNEL_TAIL_INDEX, - PrivateKernelTailToPublicArtifact: PRIVATE_KERNEL_TAIL_TO_PUBLIC_INDEX, - BaseParityArtifact: BASE_PARITY_INDEX, - RootParityArtifact: ROOT_PARITY_INDEX, - PrivateBaseRollupArtifact: PRIVATE_BASE_ROLLUP_VK_INDEX, - PublicBaseRollupArtifact: PUBLIC_BASE_ROLLUP_VK_INDEX, - MergeRollupArtifact: MERGE_ROLLUP_INDEX, - BlockRootRollupArtifact: BLOCK_ROOT_ROLLUP_INDEX, - SingleTxBlockRootRollupArtifact: BLOCK_ROOT_ROLLUP_SINGLE_TX_INDEX, - EmptyBlockRootRollupArtifact: BLOCK_ROOT_ROLLUP_EMPTY_INDEX, - BlockMergeRollupArtifact: BLOCK_MERGE_ROLLUP_INDEX, - RootRollupArtifact: ROOT_ROLLUP_INDEX, - ...PrivateKernelResetVkIndexes, -}; - -async function buildVKTree() { - const calculator = await MerkleTreeCalculator.create(VK_TREE_HEIGHT, Buffer.alloc(32), async (a, b) => - (await poseidon2Hash([a, b])).toBuffer(), - ); - const vkHashes = new Array(2 ** VK_TREE_HEIGHT).fill(Buffer.alloc(32)); - - for (const [key, value] of Object.entries(ProtocolCircuitVks)) { - const index = ProtocolCircuitVkIndexes[key as ProtocolArtifact]; - vkHashes[index] = value.keyAsFields.hash.toBuffer(); - } - - vkHashes[TUBE_VK_INDEX] = TubeVk.keyAsFields.hash.toBuffer(); - - return calculator.computeTree(vkHashes); -} - -let vkTree: MerkleTree | undefined; - -export async function getVKTree() { - if (!vkTree) { - vkTree = await buildVKTree(); - } +export function getVKTree() { return vkTree; } -export async function getVKTreeRoot() { - const tree = await getVKTree(); - return Fr.fromBuffer(tree.root); +export function getVKTreeRoot() { + return Fr.fromBuffer(vkTree.root); } -export async function getVKIndex(vk: VerificationKeyData | VerificationKeyAsFields | Fr) { +export function getVKIndex(vk: VerificationKeyData | VerificationKeyAsFields | Fr) { let hash; if (vk instanceof VerificationKeyData) { hash = vk.keyAsFields.hash; @@ -130,19 +23,16 @@ export async function getVKIndex(vk: VerificationKeyData | VerificationKeyAsFiel hash = vk; } - const tree = await getVKTree(); - - const index = tree.getIndex(hash.toBuffer()); + const index = vkTree.getIndex(hash.toBuffer()); if (index < 0) { throw new Error(`VK index for ${hash.toString()} not found in VK tree`); } return index; } -export async function getVKSiblingPath(vkIndex: number) { - const tree = await getVKTree(); +export function getVKSiblingPath(vkIndex: number) { return assertLength( - tree.getSiblingPath(vkIndex).map(buf => new Fr(buf)), + vkTree.getSiblingPath(vkIndex).map(buf => new Fr(buf)), VK_TREE_HEIGHT, ); } diff --git a/yarn-project/noir-protocol-circuits-types/src/scripts/generate_vk_tree.ts b/yarn-project/noir-protocol-circuits-types/src/scripts/generate_vk_tree.ts new file mode 100644 index 00000000000..813739e30f9 --- /dev/null +++ b/yarn-project/noir-protocol-circuits-types/src/scripts/generate_vk_tree.ts @@ -0,0 +1,54 @@ +import { MerkleTreeCalculator, TUBE_VK_INDEX, VK_TREE_HEIGHT } from '@aztec/circuits.js'; +import { poseidon2Hash } from '@aztec/foundation/crypto'; +import { createConsoleLogger } from '@aztec/foundation/log'; +import { fileURLToPath } from '@aztec/foundation/url'; + +import { promises as fs } from 'fs'; + +import type { ProtocolArtifact } from '../artifacts/types.js'; +import { ProtocolCircuitVkIndexes, ProtocolCircuitVks, TubeVk } from '../artifacts/vks.js'; + +const log = createConsoleLogger('autogenerate'); + +function resolveRelativePath(relativePath: string) { + return fileURLToPath(new URL(relativePath, import.meta.url).href); +} + +async function buildVKTree() { + const calculator = await MerkleTreeCalculator.create(VK_TREE_HEIGHT, Buffer.alloc(32), async (a, b) => + (await poseidon2Hash([a, b])).toBuffer(), + ); + + const vkHashes = new Array(2 ** VK_TREE_HEIGHT).fill(Buffer.alloc(32)); + for (const [key, value] of Object.entries(ProtocolCircuitVks)) { + const index = ProtocolCircuitVkIndexes[key as ProtocolArtifact]; + vkHashes[index] = value.keyAsFields.hash.toBuffer(); + } + + vkHashes[TUBE_VK_INDEX] = TubeVk.keyAsFields.hash.toBuffer(); + + return calculator.computeTree(vkHashes); +} + +async function main() { + const vkTree = await buildVKTree(); + const vkTreePath = resolveRelativePath('../vk_tree.ts'); + const vkTreeFileContents = ` +import { MerkleTree } from '@aztec/circuits.js'; + +export const vkTree = new MerkleTree(${vkTree.height}, [${vkTree.nodes + .map(node => `'${node.toString('hex')}'`) + .join(', ')} +].map(hex => Buffer.from(hex, 'hex'))); +`; + + await fs.writeFile(vkTreePath, vkTreeFileContents); + log(`Wrote vk tree to ${vkTreePath}`); +} + +try { + await main(); +} catch (err: unknown) { + log(`Error generating vk tree ${err}`); + process.exit(1); +} diff --git a/yarn-project/p2p/package.json b/yarn-project/p2p/package.json index 93c01eca969..cfdf14ea188 100644 --- a/yarn-project/p2p/package.json +++ b/yarn-project/p2p/package.json @@ -68,6 +68,8 @@ "@aztec/epoch-cache": "workspace:^", "@aztec/foundation": "workspace:^", "@aztec/kv-store": "workspace:^", + "@aztec/noir-protocol-circuits-types": "workspace:^", + "@aztec/protocol-contracts": "workspace:^", "@aztec/telemetry-client": "workspace:^", "@chainsafe/discv5": "9.0.0", "@chainsafe/enr": "3.0.0", diff --git a/yarn-project/p2p/src/bootstrap/bootstrap.ts b/yarn-project/p2p/src/bootstrap/bootstrap.ts index 1fda6fa5c41..da322ca599a 100644 --- a/yarn-project/p2p/src/bootstrap/bootstrap.ts +++ b/yarn-project/p2p/src/bootstrap/bootstrap.ts @@ -9,8 +9,8 @@ import type { PeerId } from '@libp2p/interface'; import { type Multiaddr, multiaddr } from '@multiformats/multiaddr'; import type { BootnodeConfig } from '../config.js'; -import { AZTEC_ENR_KEY, AZTEC_NET } from '../services/types.js'; import { convertToMultiaddr, createLibP2PPeerIdFromPrivateKey, getPeerIdPrivateKey } from '../util.js'; +import { setAztecEnrKey } from '../versioning.js'; /** * Encapsulates a 'Bootstrap' node, used for the purpose of assisting new joiners in acquiring peers. @@ -46,7 +46,8 @@ export class BootstrapNode implements P2PBootstrapApi { const publicAddr = multiaddr(convertToMultiaddr(udpAnnounceAddress, 'udp')); enr.setLocationMultiaddr(publicAddr); - enr.set(AZTEC_ENR_KEY, Uint8Array.from([AZTEC_NET])); + + const versions = setAztecEnrKey(enr, config); this.logger.debug(`Starting bootstrap node ${peerId} listening on ${listenAddrUdp.toString()}`); @@ -72,7 +73,12 @@ export class BootstrapNode implements P2PBootstrapApi { try { await this.node.start(); - this.logger.info('Bootstrap node started', { peerId, enr: enr.encodeTxt(), addr: listenAddrUdp.toString() }); + this.logger.info('Bootstrap node started', { + peerId, + enr: enr.encodeTxt(), + addr: listenAddrUdp.toString(), + versions, + }); } catch (e) { this.logger.error('Error starting Discv5', e); } diff --git a/yarn-project/p2p/src/config.ts b/yarn-project/p2p/src/config.ts index 1835dc946a2..c5be25ae8e5 100644 --- a/yarn-project/p2p/src/config.ts +++ b/yarn-project/p2p/src/config.ts @@ -1,3 +1,4 @@ +import { type ChainConfig, chainConfigMappings } from '@aztec/circuit-types/config'; import { type ConfigMappingsType, booleanConfigHelper, @@ -13,7 +14,7 @@ import { type P2PReqRespConfig, p2pReqRespConfigMappings } from './services/reqr /** * P2P client configuration values. */ -export interface P2PConfig extends P2PReqRespConfig { +export interface P2PConfig extends P2PReqRespConfig, ChainConfig { /** * A flag dictating whether the P2P subsystem should be enabled. */ @@ -69,6 +70,9 @@ export interface P2PConfig extends P2PReqRespConfig { */ bootstrapNodes: string[]; + /** Whether to execute the version check in the bootstrap node ENR. */ + bootstrapNodeEnrVersionCheck: boolean; + /** * Protocol identifier for transaction gossiping. */ @@ -150,11 +154,6 @@ export interface P2PConfig extends P2PReqRespConfig { */ peerPenaltyValues: number[]; - /** - * The chain id of the L1 chain. - */ - l1ChainId: number; - /** Limit of transactions to archive in the tx pool. Once the archived tx limit is reached, the oldest archived txs will be purged. */ archivedTxLimit: number; } @@ -209,6 +208,11 @@ export const p2pConfigMappings: ConfigMappingsType = { parseEnv: (val: string) => val.split(','), description: 'A list of bootstrap peer ENRs to connect to. Separated by commas.', }, + bootstrapNodeEnrVersionCheck: { + env: 'P2P_BOOTSTRAP_NODE_ENR_VERSION_CHECK', + description: 'Whether to check the version of the bootstrap node ENR.', + ...booleanConfigHelper(), + }, transactionProtocol: { env: 'P2P_TX_PROTOCOL', description: 'Protocol identifier for transaction gossiping.', @@ -298,11 +302,6 @@ export const p2pConfigMappings: ConfigMappingsType = { description: 'The "age" (in L2 blocks) of a tx after which we heavily penalize a peer for sending it.', ...numberConfigHelper(30), }, - l1ChainId: { - env: 'L1_CHAIN_ID', - description: 'The chain id of the L1 chain.', - ...numberConfigHelper(31337), - }, blockRequestBatchSize: { env: 'P2P_BLOCK_REQUEST_BATCH_SIZE', description: 'The number of blocks to fetch in a single batch.', @@ -315,6 +314,7 @@ export const p2pConfigMappings: ConfigMappingsType = { ...numberConfigHelper(0), }, ...p2pReqRespConfigMappings, + ...chainConfigMappings, }; /** @@ -337,7 +337,8 @@ export type BootnodeConfig = Pick< 'udpAnnounceAddress' | 'peerIdPrivateKey' | 'minPeerCount' | 'maxPeerCount' > & Required> & - Pick; + Pick & + ChainConfig; const bootnodeConfigKeys: (keyof BootnodeConfig)[] = [ 'udpAnnounceAddress', diff --git a/yarn-project/p2p/src/mocks/index.ts b/yarn-project/p2p/src/mocks/index.ts index 41120411f8e..7767b510b29 100644 --- a/yarn-project/p2p/src/mocks/index.ts +++ b/yarn-project/p2p/src/mocks/index.ts @@ -5,6 +5,7 @@ import { type Tx, type WorldStateSynchronizer, } from '@aztec/circuit-types'; +import { type ChainConfig, emptyChainConfig } from '@aztec/circuit-types/config'; import { type EpochCache } from '@aztec/epoch-cache'; import { timesParallel } from '@aztec/foundation/collection'; import { type DataStoreConfig } from '@aztec/kv-store/config'; @@ -105,6 +106,7 @@ export async function createTestLibP2PService( telemetry: TelemetryClient, port: number = 0, peerId?: PeerId, + chainConfig: ChainConfig = emptyChainConfig, ) { peerId = peerId ?? (await createSecp256k1PeerId()); const config = { @@ -118,6 +120,8 @@ export async function createTestLibP2PService( maxPeerCount: 5, p2pEnabled: true, peerIdPrivateKey: Buffer.from(peerId.privateKey!).toString('hex'), + bootstrapNodeEnrVersionCheck: false, + ...chainConfig, } as P2PConfig & DataStoreConfig; const discoveryService = new DiscV5Service(peerId, config, telemetry); const proofVerifier = new AlwaysTrueCircuitVerifier(); @@ -230,7 +234,7 @@ export class AlwaysFalseCircuitVerifier implements ClientProtocolCircuitVerifier } // Bootnodes -export function createBootstrapNodeConfig(privateKey: string, port: number): BootnodeConfig { +export function createBootstrapNodeConfig(privateKey: string, port: number, chainConfig: ChainConfig): BootnodeConfig { return { udpListenAddress: `0.0.0.0:${port}`, udpAnnounceAddress: `127.0.0.1:${port}`, @@ -239,6 +243,7 @@ export function createBootstrapNodeConfig(privateKey: string, port: number): Boo maxPeerCount: 100, dataDirectory: undefined, dataStoreMapSizeKB: 0, + ...chainConfig, }; } @@ -246,17 +251,19 @@ export function createBootstrapNodeFromPrivateKey( privateKey: string, port: number, telemetry: TelemetryClient = getTelemetryClient(), + chainConfig: ChainConfig = emptyChainConfig, ): Promise { - const config = createBootstrapNodeConfig(privateKey, port); + const config = createBootstrapNodeConfig(privateKey, port, chainConfig); return startBootstrapNode(config, telemetry); } export async function createBootstrapNode( port: number, telemetry: TelemetryClient = getTelemetryClient(), + chainConfig: ChainConfig = emptyChainConfig, ): Promise { const peerId = await createSecp256k1PeerId(); - const config = createBootstrapNodeConfig(Buffer.from(peerId.privateKey!).toString('hex'), port); + const config = createBootstrapNodeConfig(Buffer.from(peerId.privateKey!).toString('hex'), port, chainConfig); return startBootstrapNode(config, telemetry); } diff --git a/yarn-project/p2p/src/services/discv5/discV5_service.ts b/yarn-project/p2p/src/services/discv5/discV5_service.ts index 3c8d135c47b..7ecf7c331eb 100644 --- a/yarn-project/p2p/src/services/discv5/discV5_service.ts +++ b/yarn-project/p2p/src/services/discv5/discV5_service.ts @@ -1,3 +1,4 @@ +import { type ComponentsVersions, checkCompressedComponentVersion } from '@aztec/circuit-types'; import { createLogger } from '@aztec/foundation/log'; import { sleep } from '@aztec/foundation/sleep'; import { OtelMetricsAdapter, type TelemetryClient, getTelemetryClient } from '@aztec/telemetry-client'; @@ -10,8 +11,9 @@ import EventEmitter from 'events'; import type { P2PConfig } from '../../config.js'; import { convertToMultiaddr } from '../../util.js'; +import { setAztecEnrKey } from '../../versioning.js'; import { type PeerDiscoveryService, PeerDiscoveryState } from '../service.js'; -import { AZTEC_ENR_KEY, AZTEC_NET, Discv5Event, PeerEvent } from '../types.js'; +import { AZTEC_ENR_KEY, Discv5Event, PeerEvent } from '../types.js'; const delayBeforeStart = 2000; // 2sec @@ -25,6 +27,9 @@ export class DiscV5Service extends EventEmitter implements PeerDiscoveryService /** This instance's ENR */ private enr: SignableENR; + /** Version identifiers. */ + private versions: ComponentsVersions; + /** UDP listen addr */ private listenMultiAddrUdp: Multiaddr; @@ -37,7 +42,7 @@ export class DiscV5Service extends EventEmitter implements PeerDiscoveryService constructor( private peerId: PeerId, - config: P2PConfig, + private config: P2PConfig, telemetry: TelemetryClient = getTelemetryClient(), private logger = createLogger('p2p:discv5_service'), ) { @@ -47,7 +52,7 @@ export class DiscV5Service extends EventEmitter implements PeerDiscoveryService // create ENR from PeerId this.enr = SignableENR.createFromPeerId(peerId); // Add aztec identification to ENR - this.enr.set(AZTEC_ENR_KEY, Uint8Array.from([AZTEC_NET])); + this.versions = setAztecEnrKey(this.enr, config); if (!tcpAnnounceAddress) { throw new Error('You need to provide at least a TCP announce address.'); @@ -78,6 +83,20 @@ export class DiscV5Service extends EventEmitter implements PeerDiscoveryService metricsRegistry, }); + // Hook onto the onEstablished method to check the peer's version from the ENR, + // so we don't add it to our dht if it doesn't have the correct version. + // In addition, we'll hook onto onDiscovered to to repeat the same check there, + // just in case. Note that not adding the peer to the dht could lead to it + // being "readded" constantly, we'll need to keep an eye on whether this + // turns out to be a problem or not. + const origOnEstablished = this.discv5.onEstablished.bind(this.discv5); + this.discv5.onEstablished = (...args: unknown[]) => { + const enr = args[1] as ENR; + if (this.validateEnr(enr)) { + return origOnEstablished(...args); + } + }; + this.discv5.on(Discv5Event.DISCOVERED, this.onDiscovered.bind(this)); this.discv5.on(Discv5Event.ENR_ADDED, this.onEnrAdded.bind(this)); } @@ -95,20 +114,29 @@ export class DiscV5Service extends EventEmitter implements PeerDiscoveryService peerId: this.peerId, enrUdp: await this.enr.getFullMultiaddr('udp'), enrTcp: await this.enr.getFullMultiaddr('tcp'), + versions: this.versions, }); this.currentState = PeerDiscoveryState.RUNNING; // Add bootnode ENR if provided if (this.bootstrapNodes?.length) { // Do this conversion once since it involves an async function call - this.bootstrapNodePeerIds = await Promise.all(this.bootstrapNodes.map(enr => ENR.decodeTxt(enr).peerId())); - this.logger.info(`Adding bootstrap nodes ENRs: ${this.bootstrapNodes.join(', ')}`); - try { - this.bootstrapNodes.forEach(enr => { + const bootstrapNodesEnrs = this.bootstrapNodes.map(enr => ENR.decodeTxt(enr)); + this.bootstrapNodePeerIds = await Promise.all(bootstrapNodesEnrs.map(enr => enr.peerId())); + this.logger.info(`Adding ${this.bootstrapNodes} bootstrap nodes ENRs: ${this.bootstrapNodes.join(', ')}`); + for (const enr of bootstrapNodesEnrs) { + try { + if (this.config.bootstrapNodeEnrVersionCheck) { + const value = enr.kvs.get(AZTEC_ENR_KEY); + if (!value) { + throw new Error('ENR does not contain aztec key'); + } + checkCompressedComponentVersion(Buffer.from(value).toString(), this.versions); + } this.discv5.addEnr(enr); - }); - } catch (e) { - this.logger.error(`Error adding bootnode ENRs: ${e}`); + } catch (e) { + this.logger.error(`Error adding bootratrap node ${enr.encodeTxt()}`, e); + } } } } @@ -169,14 +197,35 @@ export class DiscV5Service extends EventEmitter implements PeerDiscoveryService } private onDiscovered(enr: ENR) { - // check the peer is an aztec peer + if (this.validateEnr(enr)) { + this.emit(PeerEvent.DISCOVERED, enr); + } + } + + private validateEnr(enr: ENR): boolean { + // Check the peer is an aztec peer const value = enr.kvs.get(AZTEC_ENR_KEY); - if (value) { - const network = value[0]; - // check if the peer is on the same network - if (network === AZTEC_NET) { - this.emit(PeerEvent.DISCOVERED, enr); + if (!value) { + this.logger.warn(`Peer ${enr.nodeId} does not have aztec key in ENR`); + return false; + } + + let compressedVersion; + try { + // And check it has the correct version + compressedVersion = Buffer.from(value).toString(); + checkCompressedComponentVersion(compressedVersion, this.versions); + return true; + } catch (err: any) { + if (err.name === 'ComponentsVersionsError') { + this.logger.warn(`Peer ${enr.nodeId} has incorrect version: ${err.message}`, { + compressedVersion, + expected: this.versions, + }); + } else { + this.logger.error(`Error checking peer version`, err); } } + return false; } } diff --git a/yarn-project/p2p/src/services/discv5/discv5_service.test.ts b/yarn-project/p2p/src/services/discv5/discv5_service.test.ts index b8540c732f3..f71058a2dd6 100644 --- a/yarn-project/p2p/src/services/discv5/discv5_service.test.ts +++ b/yarn-project/p2p/src/services/discv5/discv5_service.test.ts @@ -1,3 +1,5 @@ +import { emptyChainConfig } from '@aztec/circuit-types/config'; +import { addLogNameHandler } from '@aztec/foundation/log'; import { sleep } from '@aztec/foundation/sleep'; import { type AztecAsyncKVStore } from '@aztec/kv-store'; import { openTmpStore } from '@aztec/kv-store/lmdb-v2'; @@ -35,6 +37,7 @@ describe('Discv5Service', () => { let bootNode: BootstrapNode; let bootNodePeerId: PeerId; let basePort = 7890; + const baseConfig: BootnodeConfig = { udpAnnounceAddress: `127.0.0.1:${basePort + 100}`, udpListenAddress: `0.0.0.0:${basePort + 100}`, @@ -42,8 +45,13 @@ describe('Discv5Service', () => { maxPeerCount: 100, dataDirectory: undefined, dataStoreMapSizeKB: 0, + ...emptyChainConfig, }; + beforeAll(() => { + addLogNameHandler(name => (name === 'p2p:discv5_service' ? `${name}:${basePort}` : name)); + }); + beforeEach(async () => { const telemetryClient = getTelemetryClient(); store = await openTmpStore('test'); @@ -57,9 +65,13 @@ describe('Discv5Service', () => { await store.close(); }); + const startNodes = (...nodes: { start: () => Promise }[]) => Promise.all(nodes.map(node => node.start())); + const stopNodes = (...nodes: { stop: () => Promise }[]) => Promise.all(nodes.map(node => node.stop())); + const getPeers = (node: DiscV5Service) => + Promise.all(node.getAllPeers().map(async peer => (await peer.peerId()).toString())); + it('should initialize with default values', async () => { - basePort++; - const node = await createNode(basePort); + const node = await createNode(); expect(node.getStatus()).toEqual(PeerDiscoveryState.STOPPED); // not started yet await node.start(); expect(node.getStatus()).toEqual(PeerDiscoveryState.RUNNING); @@ -70,12 +82,14 @@ describe('Discv5Service', () => { }); it('should discover & add a peer', async () => { - basePort++; - const node1 = await createNode(basePort); - basePort++; - const node2 = await createNode(basePort); - await node1.start(); - await node2.start(); + const node1 = await createNode(); + const node2 = await createNode(); + await startNodes(node1, node2); + + // nodes should be connected to boostrap + expect(node1.getAllPeers()).toHaveLength(1); + expect(node2.getAllPeers()).toHaveLength(1); + await Promise.all([ waitForPeers(node2, 2), (async () => { @@ -88,25 +102,67 @@ describe('Discv5Service', () => { })(), ]); - const node1Peers = await Promise.all(node1.getAllPeers().map(async peer => (await peer.peerId()).toString())); - const node2Peers = await Promise.all(node2.getAllPeers().map(async peer => (await peer.peerId()).toString())); + const node1Peers = await getPeers(node1); + const node2Peers = await getPeers(node2); expect(node1Peers).toHaveLength(2); expect(node2Peers).toHaveLength(2); expect(node1Peers).toContain(node2.getPeerId().toString()); expect(node2Peers).toContain(node1.getPeerId().toString()); - await node1.stop(); - await node2.stop(); + await stopNodes(node1, node2); + }); + + it('should refuse to connect to a bootstrap node with wrong chain id', async () => { + const node1 = await createNode({ l1ChainId: 13, bootstrapNodeEnrVersionCheck: true }); + const node2 = await createNode({ l1ChainId: 14, bootstrapNodeEnrVersionCheck: false }); + await startNodes(node1, node2); + expect(node1.getAllPeers()).toHaveLength(0); + expect(node2.getAllPeers()).toHaveLength(1); + await stopNodes(node1, node2); + }); + + it('should not add a peer with wrong chain id', async () => { + const node1 = await createNode(); + const node2 = await createNode(); + const node3 = await createNode({ l1ChainId: 14 }); + await startNodes(node1, node2, node3); + + await Promise.all([ + waitForPeers(node1, 2), + (async () => { + await sleep(2000); // wait for peer discovery to be able to start + for (let i = 0; i < 5; i++) { + await node1.runRandomNodesQuery(); + await node2.runRandomNodesQuery(); + await node3.runRandomNodesQuery(); + await sleep(100); + } + })(), + ]); + + const node1Peers = await getPeers(node1); + const node2Peers = await getPeers(node2); + const node3Peers = await getPeers(node3); + + expect(node1Peers).toHaveLength(2); + expect(node2Peers).toHaveLength(2); + expect(node3Peers).toHaveLength(1); + + expect(node1Peers).toContain(node2.getPeerId().toString()); + expect(node1Peers).not.toContain(node3.getPeerId().toString()); + + expect(node2Peers).toContain(node1.getPeerId().toString()); + expect(node2Peers).not.toContain(node3.getPeerId().toString()); + + await stopNodes(node1, node2, node3); }); // Test is flakey, so skipping for now. // TODO: Investigate: #6246 it.skip('should persist peers without bootnode', async () => { - basePort++; - const node1 = await createNode(basePort); - basePort++; - const node2 = await createNode(basePort); + const node1 = await createNode(); + const node2 = await createNode(); await node1.start(); await node2.start(); await waitForPeers(node2, 2); @@ -126,7 +182,8 @@ describe('Discv5Service', () => { await node2.stop(); }); - const createNode = async (port: number) => { + const createNode = async (overrides: Partial = {}) => { + const port = ++basePort; const bootnodeAddr = bootNode.getENR().encodeTxt(); const peerId = await createSecp256k1PeerId(); const config: P2PConfig = { @@ -143,7 +200,7 @@ describe('Discv5Service', () => { p2pEnabled: true, l2QueueSize: 100, keepProvenTxsInPoolFor: 0, - l1ChainId: 31337, + ...overrides, }; return new DiscV5Service(peerId, config); }; diff --git a/yarn-project/p2p/src/services/reqresp/reqresp.integration.test.ts b/yarn-project/p2p/src/services/reqresp/reqresp.integration.test.ts index 44a951f66b5..e9b31b8a9d6 100644 --- a/yarn-project/p2p/src/services/reqresp/reqresp.integration.test.ts +++ b/yarn-project/p2p/src/services/reqresp/reqresp.integration.test.ts @@ -8,8 +8,9 @@ import { type WorldStateSynchronizer, mockTx, } from '@aztec/circuit-types'; +import { emptyChainConfig } from '@aztec/circuit-types/config'; import { type EpochCache } from '@aztec/epoch-cache'; -import { createLogger } from '@aztec/foundation/log'; +import { type Logger, createLogger } from '@aztec/foundation/log'; import { sleep } from '@aztec/foundation/sleep'; import { type AztecAsyncKVStore } from '@aztec/kv-store'; import { type DataStoreConfig } from '@aztec/kv-store/config'; @@ -29,8 +30,8 @@ import { type AttestationPool } from '../../mem_pools/attestation_pool/attestati import { type EpochProofQuotePool } from '../../mem_pools/epoch_proof_quote_pool/epoch_proof_quote_pool.js'; import { type TxPool } from '../../mem_pools/tx_pool/index.js'; import { AlwaysFalseCircuitVerifier, AlwaysTrueCircuitVerifier } from '../../mocks/index.js'; -import { AZTEC_ENR_KEY, AZTEC_NET } from '../../services/types.js'; import { convertToMultiaddr, createLibP2PPeerIdFromPrivateKey } from '../../util.js'; +import { setAztecEnrKey } from '../../versioning.js'; const TEST_TIMEOUT = 80000; @@ -54,7 +55,8 @@ describe('Req Resp p2p client integration', () => { let kvStore: AztecAsyncKVStore; let worldState: WorldStateSynchronizer; let proofVerifier: ClientProtocolCircuitVerifier; - const logger = createLogger('p2p:test:client-integration'); + let baseConfig: P2PConfig; + let logger: Logger; beforeEach(() => { txPool = mock(); @@ -62,6 +64,9 @@ describe('Req Resp p2p client integration', () => { epochProofQuotePool = mock(); epochCache = mock(); + baseConfig = { ...emptyChainConfig, ...getP2PDefaultConfig() }; + logger = createLogger('p2p:test:client-integration'); + txPool.getAllTxs.mockImplementation(() => { return Promise.resolve([] as Tx[]); }); @@ -86,7 +91,7 @@ describe('Req Resp p2p client integration', () => { const tcpPublicAddr = multiaddr(convertToMultiaddr(tcpAnnounceAddress, 'tcp')); // ENRS must include the network and a discoverable address (udp for discv5) - enr.set(AZTEC_ENR_KEY, Uint8Array.from([AZTEC_NET])); + setAztecEnrKey(enr, baseConfig); enr.setLocationMultiaddr(udpPublicAddr); enr.setLocationMultiaddr(tcpPublicAddr); @@ -103,7 +108,7 @@ describe('Req Resp p2p client integration', () => { const otherNodes = peerEnrs.filter((_, ind) => ind < i); const config: P2PConfig & DataStoreConfig = { - ...getP2PDefaultConfig(), + ...baseConfig, p2pEnabled: true, peerIdPrivateKey: peerIdPrivateKeys[i], tcpListenAddress: listenAddr, // run on port 0 diff --git a/yarn-project/p2p/src/services/types.ts b/yarn-project/p2p/src/services/types.ts index 16a67a724b2..72462ea3b9c 100644 --- a/yarn-project/p2p/src/services/types.ts +++ b/yarn-project/p2p/src/services/types.ts @@ -29,16 +29,8 @@ export enum GossipSubEvent { /*************************************************** * Types ***************************************************/ + /** * Aztec network specific types */ -export const AZTEC_ENR_KEY = 'aztec_network'; - -export enum AztecENR { - devnet = 0x01, - testnet = 0x02, - mainnet = 0x03, -} - -// TODO: Make this an env var -export const AZTEC_NET = AztecENR.devnet; +export const AZTEC_ENR_KEY = 'aztec'; diff --git a/yarn-project/p2p/src/versioning.test.ts b/yarn-project/p2p/src/versioning.test.ts new file mode 100644 index 00000000000..32fb8d6d541 --- /dev/null +++ b/yarn-project/p2p/src/versioning.test.ts @@ -0,0 +1,42 @@ +import { type ChainConfig } from '@aztec/circuit-types/config'; +import { EthAddress } from '@aztec/foundation/eth-address'; + +import { type SignableENR } from '@chainsafe/enr'; +import { type MockProxy, mock } from 'jest-mock-extended'; + +import { AZTEC_ENR_KEY } from './services/types.js'; +import { checkAztecEnrVersion, setAztecEnrKey } from './versioning.js'; + +describe('versioning', () => { + let enr: MockProxy; + let chainConfig: ChainConfig; + let versionSet: Buffer; + + beforeEach(() => { + enr = mock({ + set: (key, value) => { + expect(key).toEqual(AZTEC_ENR_KEY); + versionSet = Buffer.from(value); + }, + }); + + chainConfig = { + l1ChainId: 1, + l1Contracts: { + rollupAddress: EthAddress.random(), + }, + version: 3, + }; + }); + + it.each([true, false])('sets and compares versions with xxhash=%s', (useXxHash: boolean) => { + const versions = setAztecEnrKey(enr, chainConfig, useXxHash); + expect(versions.l1ChainId).toEqual(1); + expect(versions.l2ChainVersion).toEqual(3); + expect(versions.l1RollupAddress).toEqual(chainConfig.l1Contracts.rollupAddress); + expect(versionSet).toHaveLength(useXxHash ? 8 : 33); + + checkAztecEnrVersion(versionSet, versions); + expect(() => checkAztecEnrVersion(versionSet, { ...versions, l1ChainId: 3 })).toThrow(); + }); +}); diff --git a/yarn-project/p2p/src/versioning.ts b/yarn-project/p2p/src/versioning.ts new file mode 100644 index 00000000000..8c4e058cbd4 --- /dev/null +++ b/yarn-project/p2p/src/versioning.ts @@ -0,0 +1,50 @@ +import { + type ComponentsVersions, + checkCompressedComponentVersion, + compressComponentVersions, + getComponentsVersionsFromConfig, +} from '@aztec/circuit-types'; +import { type ChainConfig } from '@aztec/circuit-types/config'; +import { toBufferBE } from '@aztec/foundation/bigint-buffer'; +import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vks'; +import { protocolContractTreeRoot } from '@aztec/protocol-contracts'; + +import { type SignableENR } from '@chainsafe/enr'; +import xxhashFactory from 'xxhash-wasm'; + +import { AZTEC_ENR_KEY } from './services/types.js'; + +const USE_XX_HASH = false; // Enable to reduce the size of the ENR record for production +const XX_HASH_LEN = 8; +const xxhash = await xxhashFactory(); + +/** Returns the component versions based on config and this build. */ +export function getVersions(config: ChainConfig) { + return getComponentsVersionsFromConfig(config, protocolContractTreeRoot, getVKTreeRoot()); +} + +/** Sets the aztec key on the ENR record with versioning info. */ +export function setAztecEnrKey(enr: SignableENR, config: ChainConfig, useXxHash = USE_XX_HASH) { + const versions = getVersions(config); + const value = versionsToEnrValue(versions, useXxHash); + enr.set(AZTEC_ENR_KEY, value); + return versions; +} + +/** Checks the given value from an ENR record against the expected versions. */ +export function checkAztecEnrVersion(enrValue: Buffer, expectedVersions: ComponentsVersions) { + if (enrValue.length === XX_HASH_LEN) { + const expected = versionsToEnrValue(expectedVersions, true); + if (!Buffer.from(enrValue).equals(expected)) { + throw new Error(`Expected ENR version ${expected.toString('hex')} but received ${enrValue.toString('hex')}`); + } + } else { + const actual = Buffer.from(enrValue).toString(); + checkCompressedComponentVersion(actual, expectedVersions); + } +} + +function versionsToEnrValue(versions: ComponentsVersions, useXxHash: boolean) { + const compressed = compressComponentVersions(versions); + return useXxHash ? toBufferBE(xxhash.h64(compressed), XX_HASH_LEN) : Buffer.from(compressed); +} diff --git a/yarn-project/p2p/tsconfig.json b/yarn-project/p2p/tsconfig.json index e24bd0fd165..7e9b08f997f 100644 --- a/yarn-project/p2p/tsconfig.json +++ b/yarn-project/p2p/tsconfig.json @@ -21,6 +21,12 @@ { "path": "../kv-store" }, + { + "path": "../noir-protocol-circuits-types" + }, + { + "path": "../protocol-contracts" + }, { "path": "../telemetry-client" }, diff --git a/yarn-project/prover-client/src/block_builder/light.test.ts b/yarn-project/prover-client/src/block_builder/light.test.ts index 36419e70e39..7a92d8ac5da 100644 --- a/yarn-project/prover-client/src/block_builder/light.test.ts +++ b/yarn-project/prover-client/src/block_builder/light.test.ts @@ -96,7 +96,7 @@ describe('LightBlockBuilder', () => { beforeAll(async () => { logger = createLogger('prover-client:test:block-builder'); simulator = new TestCircuitProver(); - vkTreeRoot = await getVKTreeRoot(); + vkTreeRoot = getVKTreeRoot(); emptyProof = makeEmptyRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH); emptyRollupProof = makeEmptyRecursiveProof(NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH); db = await NativeWorldStateService.tmp(); @@ -277,7 +277,7 @@ describe('LightBlockBuilder', () => { const spongeBlobState = SpongeBlob.init(toNumBlobFields(txs)); for (const tx of txs) { const vkIndex = TUBE_VK_INDEX; - const vkPath = await getVKSiblingPath(vkIndex); + const vkPath = getVKSiblingPath(vkIndex); const vkData = new VkWitnessData(TubeVk, vkIndex, vkPath); const tubeData = new PrivateTubeData( tx.data.toPrivateToRollupKernelCircuitPublicInputs(), @@ -294,7 +294,7 @@ describe('LightBlockBuilder', () => { const getMergeOutput = async (left: BaseOrMergeRollupPublicInputs, right: BaseOrMergeRollupPublicInputs) => { const baseRollupVk = ProtocolCircuitVks['PrivateBaseRollupArtifact'].keyAsFields; - const baseRollupVkWitness = await getVkMembershipWitness(baseRollupVk); + const baseRollupVkWitness = getVkMembershipWitness(baseRollupVk); const leftInput = new PreviousRollupData(left, emptyRollupProof, baseRollupVk, baseRollupVkWitness); const rightInput = new PreviousRollupData(right, emptyRollupProof, baseRollupVk, baseRollupVkWitness); const inputs = new MergeRollupInputs([leftInput, rightInput]); @@ -308,7 +308,7 @@ describe('LightBlockBuilder', () => { const rootParityInputs: RootParityInput[] = []; const baseParityVk = ProtocolCircuitVks['BaseParityArtifact'].keyAsFields; - const baseParityVkWitness = await getVkMembershipWitness(baseParityVk); + const baseParityVkWitness = getVkMembershipWitness(baseParityVk); for (let i = 0; i < NUM_BASE_PARITY_PER_ROOT_PARITY; i++) { const input = BaseParityInputs.fromSlice(l1ToL2Messages, i, vkTreeRoot); const { inputs } = await simulator.getBaseParityProof(input); @@ -332,7 +332,7 @@ describe('LightBlockBuilder', () => { txs: ProcessedTx[], ) => { const mergeRollupVk = ProtocolCircuitVks['MergeRollupArtifact'].keyAsFields; - const mergeRollupVkWitness = await getVkMembershipWitness(mergeRollupVk); + const mergeRollupVkWitness = getVkMembershipWitness(mergeRollupVk); const previousRollupData = previousRollups.map( r => new PreviousRollupData(r, emptyRollupProof, mergeRollupVk, mergeRollupVkWitness), ); @@ -343,7 +343,7 @@ describe('LightBlockBuilder', () => { const blobs = await Blob.getBlobs(blobFields); const blobsHash = sha256ToField(blobs.map(b => b.getEthVersionedBlobHash())); const rootParityVk = ProtocolCircuitVks['RootParityArtifact'].keyAsFields; - const rootParityVkWitness = await getVkMembershipWitness(rootParityVk); + const rootParityVkWitness = getVkMembershipWitness(rootParityVk); const rootParityInput = new RootParityInput( emptyProof, @@ -366,7 +366,7 @@ describe('LightBlockBuilder', () => { const constants = ConstantRollupData.from({ lastArchive: startArchiveSnapshot, globalVariables, - vkTreeRoot: await getVKTreeRoot(), + vkTreeRoot: getVKTreeRoot(), protocolContractTreeRoot, }); const inputs = EmptyBlockRootRollupInputs.from({ @@ -404,8 +404,8 @@ describe('LightBlockBuilder', () => { } }; - async function getVkMembershipWitness(vk: VerificationKeyAsFields) { - const leafIndex = await getVKIndex(vk); - return new MembershipWitness(VK_TREE_HEIGHT, BigInt(leafIndex), await getVKSiblingPath(leafIndex)); + function getVkMembershipWitness(vk: VerificationKeyAsFields) { + const leafIndex = getVKIndex(vk); + return new MembershipWitness(VK_TREE_HEIGHT, BigInt(leafIndex), getVKSiblingPath(leafIndex)); } }); diff --git a/yarn-project/prover-client/src/mocks/test_context.ts b/yarn-project/prover-client/src/mocks/test_context.ts index 8a02c64e6be..b635187f08f 100644 --- a/yarn-project/prover-client/src/mocks/test_context.ts +++ b/yarn-project/prover-client/src/mocks/test_context.ts @@ -160,15 +160,13 @@ export class TestContext { public makeProcessedTx(opts?: Parameters[0]): Promise; public makeProcessedTx(seed?: number): Promise; - public async makeProcessedTx( - seedOrOpts?: Parameters[0] | number, - ): Promise { + public makeProcessedTx(seedOrOpts?: Parameters[0] | number): Promise { const opts = typeof seedOrOpts === 'number' ? { seed: seedOrOpts } : seedOrOpts; const blockNum = (opts?.globalVariables ?? this.globalVariables).blockNumber.toNumber(); const header = this.getBlockHeader(blockNum - 1); return makeBloatedProcessedTx({ header, - vkTreeRoot: await getVKTreeRoot(), + vkTreeRoot: getVKTreeRoot(), protocolContractTreeRoot, globalVariables: this.globalVariables, ...opts, diff --git a/yarn-project/prover-client/src/orchestrator/block-building-helpers.ts b/yarn-project/prover-client/src/orchestrator/block-building-helpers.ts index 86970228f20..6d73bd64cc6 100644 --- a/yarn-project/prover-client/src/orchestrator/block-building-helpers.ts +++ b/yarn-project/prover-client/src/orchestrator/block-building-helpers.ts @@ -441,7 +441,7 @@ export const getConstantRollupData = runInSpan( 'getConstantRollupData', async (_span, globalVariables: GlobalVariables, db: MerkleTreeReadOperations): Promise => { return ConstantRollupData.from({ - vkTreeRoot: await getVKTreeRoot(), + vkTreeRoot: getVKTreeRoot(), protocolContractTreeRoot, lastArchive: await getTreeSnapshot(MerkleTreeId.ARCHIVE, db), globalVariables, diff --git a/yarn-project/prover-client/src/orchestrator/block-proving-state.ts b/yarn-project/prover-client/src/orchestrator/block-proving-state.ts index 1cfd01f33da..8b483a308bd 100644 --- a/yarn-project/prover-client/src/orchestrator/block-proving-state.ts +++ b/yarn-project/prover-client/src/orchestrator/block-proving-state.ts @@ -164,13 +164,13 @@ export class BlockProvingState { return this.baseOrMergeProvingOutputs.getParentLocation(location); } - public async getMergeRollupInputs(mergeLocation: TreeNodeLocation) { + public getMergeRollupInputs(mergeLocation: TreeNodeLocation) { const [left, right] = this.baseOrMergeProvingOutputs.getChildren(mergeLocation); if (!left || !right) { throw new Error('At lease one child is not ready.'); } - return new MergeRollupInputs([await this.#getPreviousRollupData(left), await this.#getPreviousRollupData(right)]); + return new MergeRollupInputs([this.#getPreviousRollupData(left), this.#getPreviousRollupData(right)]); } public async getBlockRootRollupTypeAndInputs(proverId: Fr) { @@ -184,13 +184,13 @@ export class BlockProvingState { throw new Error('At lease one child is not ready for the block root.'); } - const data = await this.#getBlockRootRollupData(proverId); + const data = this.#getBlockRootRollupData(proverId); if (this.totalNumTxs === 0) { const constants = ConstantRollupData.from({ lastArchive: this.lastArchiveSnapshot, globalVariables: this.globalVariables, - vkTreeRoot: await getVKTreeRoot(), + vkTreeRoot: getVKTreeRoot(), protocolContractTreeRoot, }); @@ -234,7 +234,7 @@ export class BlockProvingState { const newArchive = this.blockRootProvingOutput!.inputs.newArchive; const data = BlockRootRollupData.from({ - l1ToL2Roots: await this.#getRootParityData(this.rootParityProvingOutput!), + l1ToL2Roots: this.#getRootParityData(this.rootParityProvingOutput!), l1ToL2MessageSubtreeSiblingPath: this.l1ToL2MessageSubtreeSiblingPath, newArchiveSiblingPath: this.newArchiveSiblingPath, previousBlockHeader: newBlockHeader, @@ -244,7 +244,7 @@ export class BlockProvingState { const constants = ConstantRollupData.from({ lastArchive: newArchive, globalVariables: this.globalVariables, - vkTreeRoot: await getVKTreeRoot(), + vkTreeRoot: getVKTreeRoot(), protocolContractTreeRoot, }); @@ -255,12 +255,12 @@ export class BlockProvingState { }); } - public async getRootParityInputs() { + public getRootParityInputs() { if (!this.baseParityProvingOutputs.every(p => !!p)) { throw new Error('At lease one base parity is not ready.'); } - const children = await Promise.all(this.baseParityProvingOutputs.map(p => this.#getRootParityData(p!))); + const children = this.baseParityProvingOutputs.map(p => this.#getRootParityData(p!)); return new RootParityInputs( children as Tuple, typeof NUM_BASE_PARITY_PER_ROOT_PARITY>, ); @@ -326,9 +326,9 @@ export class BlockProvingState { this.parentEpoch.reject(reason); } - async #getBlockRootRollupData(proverId: Fr) { + #getBlockRootRollupData(proverId: Fr) { return BlockRootRollupData.from({ - l1ToL2Roots: await this.#getRootParityData(this.rootParityProvingOutput!), + l1ToL2Roots: this.#getRootParityData(this.rootParityProvingOutput!), l1ToL2MessageSubtreeSiblingPath: this.l1ToL2MessageSubtreeSiblingPath, newArchiveSiblingPath: this.newArchiveSiblingPath, previousBlockHeader: this.previousBlockHeader, @@ -358,25 +358,25 @@ export class BlockProvingState { : this.baseOrMergeProvingOutputs.getChildren(rootLocation); } - async #getPreviousRollupData({ + #getPreviousRollupData({ inputs, proof, verificationKey, }: PublicInputsAndRecursiveProof) { - const leafIndex = await getVKIndex(verificationKey.keyAsFields); + const leafIndex = getVKIndex(verificationKey.keyAsFields); return new PreviousRollupData( inputs, proof, verificationKey.keyAsFields, - new MembershipWitness(VK_TREE_HEIGHT, BigInt(leafIndex), await getVKSiblingPath(leafIndex)), + new MembershipWitness(VK_TREE_HEIGHT, BigInt(leafIndex), getVKSiblingPath(leafIndex)), ); } - async #getRootParityData({ inputs, proof, verificationKey }: PublicInputsAndRecursiveProof) { + #getRootParityData({ inputs, proof, verificationKey }: PublicInputsAndRecursiveProof) { return new RootParityInput( proof, verificationKey.keyAsFields, - await getVKSiblingPath(await getVKIndex(verificationKey)), + getVKSiblingPath(getVKIndex(verificationKey)), inputs, ); } diff --git a/yarn-project/prover-client/src/orchestrator/epoch-proving-state.ts b/yarn-project/prover-client/src/orchestrator/epoch-proving-state.ts index 0319dabfaaf..c135e2c9f92 100644 --- a/yarn-project/prover-client/src/orchestrator/epoch-proving-state.ts +++ b/yarn-project/prover-client/src/orchestrator/epoch-proving-state.ts @@ -150,26 +150,23 @@ export class EpochProvingState { return this.blockRootOrMergeProvingOutputs.getParentLocation(location); } - public async getBlockMergeRollupInputs(mergeLocation: TreeNodeLocation) { + public getBlockMergeRollupInputs(mergeLocation: TreeNodeLocation) { const [left, right] = this.blockRootOrMergeProvingOutputs.getChildren(mergeLocation); if (!left || !right) { throw new Error('At lease one child is not ready.'); } - return new BlockMergeRollupInputs([ - await this.#getPreviousRollupData(left), - await this.#getPreviousRollupData(right), - ]); + return new BlockMergeRollupInputs([this.#getPreviousRollupData(left), this.#getPreviousRollupData(right)]); } - public async getRootRollupInputs(proverId: Fr) { + public getRootRollupInputs(proverId: Fr) { const [left, right] = this.#getChildProofsForRoot(); if (!left || !right) { throw new Error('At lease one child is not ready.'); } return RootRollupInputs.from({ - previousRollupData: [await this.#getPreviousRollupData(left), await this.#getPreviousRollupData(right)], + previousRollupData: [this.#getPreviousRollupData(left), this.#getPreviousRollupData(right)], proverId, }); } @@ -241,7 +238,7 @@ export class EpochProvingState { : this.blockRootOrMergeProvingOutputs.getChildren(rootLocation); } - async #getPreviousRollupData({ + #getPreviousRollupData({ inputs, proof, verificationKey, @@ -249,12 +246,12 @@ export class EpochProvingState { BlockRootOrBlockMergePublicInputs, typeof NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH >) { - const leafIndex = await getVKIndex(verificationKey.keyAsFields); + const leafIndex = getVKIndex(verificationKey.keyAsFields); return new PreviousRollupBlockData( inputs, proof, verificationKey.keyAsFields, - new MembershipWitness(VK_TREE_HEIGHT, BigInt(leafIndex), await getVKSiblingPath(leafIndex)), + new MembershipWitness(VK_TREE_HEIGHT, BigInt(leafIndex), getVKSiblingPath(leafIndex)), ); } } diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator.ts b/yarn-project/prover-client/src/orchestrator/orchestrator.ts index 1d8a0b855dc..e03f2aa9d37 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator.ts @@ -36,7 +36,7 @@ import { SingleTxBlockRootRollupInputs, TubeInputs, } from '@aztec/circuits.js/rollup'; -import { padArrayEnd, timesParallel } from '@aztec/foundation/collection'; +import { padArrayEnd, times } from '@aztec/foundation/collection'; import { AbortError } from '@aztec/foundation/error'; import { createLogger } from '@aztec/foundation/log'; import { promiseWithResolvers } from '@aztec/foundation/promise'; @@ -247,7 +247,7 @@ export class ProvingOrchestrator implements EpochProver { const tubeInputs = new TubeInputs(tx.clientIvcProof); const tubeProof = promiseWithResolvers>(); logger.debug(`Starting tube circuit for tx ${txHash}`); - this.doEnqueueTube(txHash, tubeInputs, proof => Promise.resolve(tubeProof.resolve(proof))); + this.doEnqueueTube(txHash, tubeInputs, proof => tubeProof.resolve(proof)); this.provingState?.cachedTubeProofs.set(txHash, tubeProof.promise); } } @@ -458,8 +458,8 @@ export class ProvingOrchestrator implements EpochProver { NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, 'Too many L1 to L2 messages', ); - const baseParityInputs = await timesParallel(NUM_BASE_PARITY_PER_ROOT_PARITY, async i => - BaseParityInputs.fromSlice(l1ToL2MessagesPadded, i, await getVKTreeRoot()), + const baseParityInputs = times(NUM_BASE_PARITY_PER_ROOT_PARITY, i => + BaseParityInputs.fromSlice(l1ToL2MessagesPadded, i, getVKTreeRoot()), ); const l1ToL2MessageSubtreeSiblingPath = assertLength( @@ -517,7 +517,7 @@ export class ProvingOrchestrator implements EpochProver { // Executes the base rollup circuit and stored the output as intermediate state for the parent merge/root circuit // Executes the next level of merge if all inputs are available - private async enqueueBaseRollup(provingState: BlockProvingState, txIndex: number) { + private enqueueBaseRollup(provingState: BlockProvingState, txIndex: number) { if (!provingState.verifyState()) { logger.debug('Not running base rollup, state invalid'); return; @@ -525,7 +525,7 @@ export class ProvingOrchestrator implements EpochProver { const txProvingState = provingState.getTxProvingState(txIndex); const { processedTx } = txProvingState; - const { rollupType, inputs } = await txProvingState.getBaseRollupTypeAndInputs(); + const { rollupType, inputs } = txProvingState.getBaseRollupTypeAndInputs(); logger.debug(`Enqueuing deferred proving base rollup for ${processedTx.hash.toString()}`); @@ -573,11 +573,11 @@ export class ProvingOrchestrator implements EpochProver { const txProvingState = provingState.getTxProvingState(txIndex); const txHash = txProvingState.processedTx.hash.toString(); - const handleResult = async (result: ProofAndVerificationKey) => { + const handleResult = (result: ProofAndVerificationKey) => { logger.debug(`Got tube proof for tx index: ${txIndex}`, { txHash }); txProvingState.setTubeProof(result); this.provingState?.cachedTubeProofs.delete(txHash); - await this.checkAndEnqueueNextTxCircuit(provingState, txIndex); + this.checkAndEnqueueNextTxCircuit(provingState, txIndex); }; if (this.provingState?.cachedTubeProofs.has(txHash)) { @@ -593,7 +593,7 @@ export class ProvingOrchestrator implements EpochProver { private doEnqueueTube( txHash: string, inputs: TubeInputs, - handler: (result: ProofAndVerificationKey) => Promise, + handler: (result: ProofAndVerificationKey) => void, provingState: EpochProvingState | BlockProvingState = this.provingState!, ) { if (!provingState?.verifyState()) { @@ -619,13 +619,13 @@ export class ProvingOrchestrator implements EpochProver { // Executes the merge rollup circuit and stored the output as intermediate state for the parent merge/block root circuit // Enqueues the next level of merge if all inputs are available - private async enqueueMergeRollup(provingState: BlockProvingState, location: TreeNodeLocation) { + private enqueueMergeRollup(provingState: BlockProvingState, location: TreeNodeLocation) { if (!provingState.verifyState()) { logger.debug('Not running merge rollup. State no longer valid.'); return; } - const inputs = await provingState.getMergeRollupInputs(location); + const inputs = provingState.getMergeRollupInputs(location); this.deferredProving( provingState, @@ -697,7 +697,7 @@ export class ProvingOrchestrator implements EpochProver { if (epochProvingState.totalNumBlocks === 1) { await this.enqueueEpochPadding(epochProvingState); } else { - await this.checkAndEnqueueNextBlockMergeRollup(epochProvingState, leafLocation); + this.checkAndEnqueueNextBlockMergeRollup(epochProvingState, leafLocation); } }, ); @@ -722,30 +722,30 @@ export class ProvingOrchestrator implements EpochProver { }, signal => this.prover.getBaseParityProof(inputs, signal, provingState.epochNumber), ), - async provingOutput => { + provingOutput => { provingState.setBaseParityProof(index, provingOutput); - await this.checkAndEnqueueRootParityCircuit(provingState); + this.checkAndEnqueueRootParityCircuit(provingState); }, ); } - private async checkAndEnqueueRootParityCircuit(provingState: BlockProvingState) { + private checkAndEnqueueRootParityCircuit(provingState: BlockProvingState) { if (!provingState.isReadyForRootParity()) { return; } - await this.enqueueRootParityCircuit(provingState); + this.enqueueRootParityCircuit(provingState); } // Runs the root parity circuit ans stored the outputs // Enqueues the root rollup proof if all inputs are available - private async enqueueRootParityCircuit(provingState: BlockProvingState) { + private enqueueRootParityCircuit(provingState: BlockProvingState) { if (!provingState.verifyState()) { logger.debug('Not running root parity. State no longer valid.'); return; } - const inputs = await provingState.getRootParityInputs(); + const inputs = provingState.getRootParityInputs(); this.deferredProving( provingState, @@ -767,13 +767,13 @@ export class ProvingOrchestrator implements EpochProver { // Executes the block merge rollup circuit and stored the output as intermediate state for the parent merge/block root circuit // Enqueues the next level of merge if all inputs are available - private async enqueueBlockMergeRollup(provingState: EpochProvingState, location: TreeNodeLocation) { + private enqueueBlockMergeRollup(provingState: EpochProvingState, location: TreeNodeLocation) { if (!provingState.verifyState()) { logger.debug('Not running block merge rollup. State no longer valid.'); return; } - const inputs = await provingState.getBlockMergeRollupInputs(location); + const inputs = provingState.getBlockMergeRollupInputs(location); this.deferredProving( provingState, @@ -786,9 +786,9 @@ export class ProvingOrchestrator implements EpochProver { }, signal => this.prover.getBlockMergeRollupProof(inputs, signal, provingState.epochNumber), ), - async result => { + result => { provingState.setBlockMergeRollupProof(location, result); - await this.checkAndEnqueueNextBlockMergeRollup(provingState, location); + this.checkAndEnqueueNextBlockMergeRollup(provingState, location); }, ); } @@ -814,16 +814,16 @@ export class ProvingOrchestrator implements EpochProver { }, signal => this.prover.getEmptyBlockRootRollupProof(inputs, signal, provingState.epochNumber), ), - async result => { + result => { logger.debug('Completed proof for padding block root.'); provingState.setPaddingBlockRootProof(result); - await this.checkAndEnqueueRootRollup(provingState); + this.checkAndEnqueueRootRollup(provingState); }, ); } // Executes the root rollup circuit - private async enqueueRootRollup(provingState: EpochProvingState) { + private enqueueRootRollup(provingState: EpochProvingState) { if (!provingState.verifyState()) { logger.debug('Not running root rollup, state no longer valid'); return; @@ -831,7 +831,7 @@ export class ProvingOrchestrator implements EpochProver { logger.debug(`Preparing root rollup`); - const inputs = await provingState.getRootRollupInputs(this.proverId); + const inputs = provingState.getRootRollupInputs(this.proverId); this.deferredProving( provingState, @@ -861,7 +861,7 @@ export class ProvingOrchestrator implements EpochProver { if (parentLocation.level === 0) { await this.checkAndEnqueueBlockRootRollup(provingState); } else { - await this.enqueueMergeRollup(provingState, parentLocation); + this.enqueueMergeRollup(provingState, parentLocation); } } @@ -890,29 +890,26 @@ export class ProvingOrchestrator implements EpochProver { await this.enqueueBlockRootRollup(provingState); } - private async checkAndEnqueueNextBlockMergeRollup( - provingState: EpochProvingState, - currentLocation: TreeNodeLocation, - ) { + private checkAndEnqueueNextBlockMergeRollup(provingState: EpochProvingState, currentLocation: TreeNodeLocation) { if (!provingState.isReadyForBlockMerge(currentLocation)) { return; } const parentLocation = provingState.getParentLocation(currentLocation); if (parentLocation.level === 0) { - await this.checkAndEnqueueRootRollup(provingState); + this.checkAndEnqueueRootRollup(provingState); } else { - await this.enqueueBlockMergeRollup(provingState, parentLocation); + this.enqueueBlockMergeRollup(provingState, parentLocation); } } - private async checkAndEnqueueRootRollup(provingState: EpochProvingState) { + private checkAndEnqueueRootRollup(provingState: EpochProvingState) { if (!provingState.isReadyForRootRollup()) { logger.debug('Not ready for root rollup'); return; } - await this.enqueueRootRollup(provingState); + this.enqueueRootRollup(provingState); } /** @@ -960,14 +957,14 @@ export class ProvingOrchestrator implements EpochProver { }, ); - this.deferredProving(provingState, doAvmProving, async proofAndVk => { + this.deferredProving(provingState, doAvmProving, proofAndVk => { logger.debug(`Proven VM for tx index: ${txIndex}`); txProvingState.setAvmProof(proofAndVk); - await this.checkAndEnqueueNextTxCircuit(provingState, txIndex); + this.checkAndEnqueueNextTxCircuit(provingState, txIndex); }); } - private async checkAndEnqueueNextTxCircuit(provingState: BlockProvingState, txIndex: number) { + private checkAndEnqueueNextTxCircuit(provingState: BlockProvingState, txIndex: number) { const txProvingState = provingState.getTxProvingState(txIndex); if (!txProvingState.ready()) { return; @@ -976,6 +973,6 @@ export class ProvingOrchestrator implements EpochProver { // We must have completed all proving (tube proof and (if required) vm proof are generated), we now move to the base rollup. logger.debug(`Public functions completed for tx ${txIndex} enqueueing base rollup`); - await this.enqueueBaseRollup(provingState, txIndex); + this.enqueueBaseRollup(provingState, txIndex); } } diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator_multi_public_functions.test.ts b/yarn-project/prover-client/src/orchestrator/orchestrator_multi_public_functions.test.ts index b70a3a4d10c..9ace6e58d11 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator_multi_public_functions.test.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator_multi_public_functions.test.ts @@ -36,7 +36,7 @@ describe('prover/orchestrator/public-functions', () => { ); for (const tx of txs) { tx.data.constants.historicalHeader = context.getBlockHeader(0); - tx.data.constants.vkTreeRoot = await getVKTreeRoot(); + tx.data.constants.vkTreeRoot = getVKTreeRoot(); tx.data.constants.protocolContractTreeRoot = protocolContractTreeRoot; } diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator_public_functions.test.ts b/yarn-project/prover-client/src/orchestrator/orchestrator_public_functions.test.ts index f24e0fd3054..8bdb07daece 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator_public_functions.test.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator_public_functions.test.ts @@ -41,7 +41,7 @@ describe('prover/orchestrator/public-functions', () => { numberOfRevertiblePublicCallRequests, }); tx.data.constants.historicalHeader = context.getBlockHeader(0); - tx.data.constants.vkTreeRoot = await getVKTreeRoot(); + tx.data.constants.vkTreeRoot = getVKTreeRoot(); tx.data.constants.protocolContractTreeRoot = protocolContractTreeRoot; const [processed, _] = await context.processPublicFunctions([tx], 1); @@ -67,7 +67,7 @@ describe('prover/orchestrator/public-functions', () => { numberOfNonRevertiblePublicCallRequests: 2, }); tx.data.constants.historicalHeader = context.getBlockHeader(0); - tx.data.constants.vkTreeRoot = await getVKTreeRoot(); + tx.data.constants.vkTreeRoot = getVKTreeRoot(); tx.data.constants.protocolContractTreeRoot = protocolContractTreeRoot; const [processed, _] = await context.processPublicFunctions([tx], 1); diff --git a/yarn-project/prover-client/src/orchestrator/tx-proving-state.ts b/yarn-project/prover-client/src/orchestrator/tx-proving-state.ts index 11f96c9569f..ebdca3931ca 100644 --- a/yarn-project/prover-client/src/orchestrator/tx-proving-state.ts +++ b/yarn-project/prover-client/src/orchestrator/tx-proving-state.ts @@ -52,16 +52,16 @@ export class TxProvingState { return this.processedTx.avmProvingRequest!.inputs; } - public async getBaseRollupTypeAndInputs() { + public getBaseRollupTypeAndInputs() { if (this.requireAvmProof) { return { rollupType: 'public-base-rollup' satisfies CircuitName, - inputs: await this.#getPublicBaseInputs(), + inputs: this.#getPublicBaseInputs(), }; } else { return { rollupType: 'private-base-rollup' satisfies CircuitName, - inputs: await this.#getPrivateBaseInputs(), + inputs: this.#getPrivateBaseInputs(), }; } } @@ -74,12 +74,12 @@ export class TxProvingState { this.avm = avmProofAndVk; } - async #getPrivateBaseInputs() { + #getPrivateBaseInputs() { if (!this.tube) { throw new Error('Tx not ready for proving base rollup.'); } - const vkData = await this.#getTubeVkData(); + const vkData = this.#getTubeVkData(); const tubeData = new PrivateTubeData( this.processedTx.data.toPrivateToRollupKernelCircuitPublicInputs(), this.tube.proof, @@ -92,7 +92,7 @@ export class TxProvingState { return new PrivateBaseRollupInputs(tubeData, this.baseRollupHints); } - async #getPublicBaseInputs() { + #getPublicBaseInputs() { if (!this.processedTx.avmProvingRequest) { throw new Error('Should create private base rollup for a tx not requiring avm proof.'); } @@ -106,13 +106,13 @@ export class TxProvingState { const tubeData = new PublicTubeData( this.processedTx.data.toPrivateToPublicKernelCircuitPublicInputs(), this.tube.proof, - await this.#getTubeVkData(), + this.#getTubeVkData(), ); const avmProofData = new AvmProofData( this.processedTx.avmProvingRequest.inputs.publicInputs, this.avm.proof, - await this.#getAvmVkData(), + this.#getAvmVkData(), ); if (!(this.baseRollupHints instanceof PublicBaseRollupHints)) { @@ -122,21 +122,21 @@ export class TxProvingState { return new PublicBaseRollupInputs(tubeData, avmProofData, this.baseRollupHints); } - async #getTubeVkData() { + #getTubeVkData() { let vkIndex = TUBE_VK_INDEX; try { - vkIndex = await getVKIndex(this.tube!.verificationKey); + vkIndex = getVKIndex(this.tube!.verificationKey); } catch (_ignored) { // TODO(#7410) The VK for the tube won't be in the tree for now, so we manually set it to the tube vk index } - const vkPath = await getVKSiblingPath(vkIndex); + const vkPath = getVKSiblingPath(vkIndex); return new VkWitnessData(this.tube!.verificationKey, vkIndex, vkPath); } - async #getAvmVkData() { + #getAvmVkData() { const vkIndex = AVM_VK_INDEX; - const vkPath = await getVKSiblingPath(vkIndex); + const vkPath = getVKSiblingPath(vkIndex); return new VkWitnessData(this.avm!.verificationKey, AVM_VK_INDEX, vkPath); } } diff --git a/yarn-project/prover-client/src/prover-agent/rpc.ts b/yarn-project/prover-client/src/prover-agent/rpc.ts index 14d8d3c90a6..f3ccf529687 100644 --- a/yarn-project/prover-client/src/prover-agent/rpc.ts +++ b/yarn-project/prover-client/src/prover-agent/rpc.ts @@ -1,4 +1,10 @@ -import { ProverAgentApiSchema, type ProvingJobSource, ProvingJobSourceSchema } from '@aztec/circuit-types'; +import { + type ComponentsVersions, + ProverAgentApiSchema, + type ProvingJobSource, + ProvingJobSourceSchema, + getVersioningResponseHandler, +} from '@aztec/circuit-types'; import { createSafeJsonRpcClient } from '@aztec/foundation/json-rpc/client'; import { createTracedJsonRpcServer, makeTracedFetch } from '@aztec/telemetry-client'; @@ -8,8 +14,16 @@ export function createProvingJobSourceServer(queue: ProvingJobSource) { return createTracedJsonRpcServer(queue, ProvingJobSourceSchema); } -export function createProvingJobSourceClient(url: string, fetch = makeTracedFetch([1, 2, 3], false)): ProvingJobSource { - return createSafeJsonRpcClient(url, ProvingJobSourceSchema, false, 'provingJobSource', fetch); +export function createProvingJobSourceClient( + url: string, + versions: Partial, + fetch = makeTracedFetch([1, 2, 3], false), +): ProvingJobSource { + return createSafeJsonRpcClient(url, ProvingJobSourceSchema, { + namespaceMethods: 'provingJobSource', + fetch, + onResponse: getVersioningResponseHandler(versions), + }); } /** diff --git a/yarn-project/prover-client/src/proving_broker/rpc.ts b/yarn-project/prover-client/src/proving_broker/rpc.ts index 63d2a5ca4c9..77de87d9ef2 100644 --- a/yarn-project/prover-client/src/proving_broker/rpc.ts +++ b/yarn-project/prover-client/src/proving_broker/rpc.ts @@ -1,4 +1,5 @@ import { + type ComponentsVersions, type GetProvingJobResponse, ProofUri, ProvingJob, @@ -8,6 +9,7 @@ import { type ProvingJobProducer, ProvingJobStatus, ProvingRequestType, + getVersioningResponseHandler, } from '@aztec/circuit-types'; import { createSafeJsonRpcClient } from '@aztec/foundation/json-rpc/client'; import { type SafeJsonRpcServer } from '@aztec/foundation/json-rpc/server'; @@ -57,20 +59,38 @@ export function createProvingBrokerServer(broker: ProvingJobBroker): SafeJsonRpc return createTracedJsonRpcServer(broker, ProvingJobBrokerSchema); } -export function createProvingJobBrokerClient(url: string, fetch = makeTracedFetch([1, 2, 3], false)): ProvingJobBroker { - return createSafeJsonRpcClient(url, ProvingJobBrokerSchema, false, 'proverBroker', fetch); +export function createProvingJobBrokerClient( + url: string, + versions: Partial, + fetch = makeTracedFetch([1, 2, 3], false), +): ProvingJobBroker { + return createSafeJsonRpcClient(url, ProvingJobBrokerSchema, { + namespaceMethods: 'proverBroker', + fetch, + onResponse: getVersioningResponseHandler(versions), + }); } export function createProvingJobProducerClient( url: string, + versions: Partial, fetch = makeTracedFetch([1, 2, 3], false), ): ProvingJobProducer { - return createSafeJsonRpcClient(url, ProvingJobProducerSchema, false, 'provingJobProducer', fetch); + return createSafeJsonRpcClient(url, ProvingJobProducerSchema, { + namespaceMethods: 'provingJobProducer', + fetch, + onResponse: getVersioningResponseHandler(versions), + }); } export function createProvingJobConsumerClient( url: string, + versions: Partial, fetch = makeTracedFetch([1, 2, 3], false), ): ProvingJobConsumer { - return createSafeJsonRpcClient(url, ProvingJobConsumerSchema, false, 'provingJobConsumer', fetch); + return createSafeJsonRpcClient(url, ProvingJobConsumerSchema, { + namespaceMethods: 'provingJobConsumer', + fetch, + onResponse: getVersioningResponseHandler(versions), + }); } diff --git a/yarn-project/prover-client/src/test/bb_prover_full_rollup.test.ts b/yarn-project/prover-client/src/test/bb_prover_full_rollup.test.ts index 76933ac092b..2eaafe7938c 100644 --- a/yarn-project/prover-client/src/test/bb_prover_full_rollup.test.ts +++ b/yarn-project/prover-client/src/test/bb_prover_full_rollup.test.ts @@ -50,7 +50,7 @@ describe('prover/bb_prover/full-rollup', () => { const txOpts = { numberOfNonRevertiblePublicCallRequests: 0, numberOfRevertiblePublicCallRequests: 0 }; const tx = await mockTx(blockNum * 100_000 + 1000 * (i + 1), txOpts); tx.data.constants.historicalHeader = initialHeader; - tx.data.constants.vkTreeRoot = await getVKTreeRoot(); + tx.data.constants.vkTreeRoot = getVKTreeRoot(); return tx; }); diff --git a/yarn-project/prover-client/src/test/bb_prover_parity.test.ts b/yarn-project/prover-client/src/test/bb_prover_parity.test.ts index cd6e9f8fd90..1f65db5607f 100644 --- a/yarn-project/prover-client/src/test/bb_prover_parity.test.ts +++ b/yarn-project/prover-client/src/test/bb_prover_parity.test.ts @@ -11,7 +11,7 @@ import { VerificationKeyAsFields, makeRecursiveProof, } from '@aztec/circuits.js'; -import { makeTuple, makeTupleAsync } from '@aztec/foundation/array'; +import { makeTuple } from '@aztec/foundation/array'; import { randomBytes } from '@aztec/foundation/crypto'; import { createLogger } from '@aztec/foundation/log'; import { @@ -47,8 +47,8 @@ describe('prover/bb_prover/parity', () => { NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, Fr.random, ); - const baseParityInputs = await makeTupleAsync(NUM_BASE_PARITY_PER_ROOT_PARITY, async i => - BaseParityInputs.fromSlice(l1ToL2Messages, i, await getVKTreeRoot()), + const baseParityInputs = makeTuple(NUM_BASE_PARITY_PER_ROOT_PARITY, i => + BaseParityInputs.fromSlice(l1ToL2Messages, i, getVKTreeRoot()), ); // Generate the base parity proofs @@ -56,12 +56,12 @@ describe('prover/bb_prover/parity', () => { baseParityInputs.map(baseInputs => context.prover.getBaseParityProof(baseInputs)), ); - const rootInputs = await makeTupleAsync(NUM_BASE_PARITY_PER_ROOT_PARITY, async i => { + const rootInputs = makeTuple(NUM_BASE_PARITY_PER_ROOT_PARITY, i => { const { proof, inputs, verificationKey } = baseParityProofsAndPublicInputs[i]; return new RootParityInput( proof, verificationKey.keyAsFields, - await getVKSiblingPath(ProtocolCircuitVkIndexes.BaseParityArtifact), + getVKSiblingPath(ProtocolCircuitVkIndexes.BaseParityArtifact), inputs, ); }); @@ -93,7 +93,7 @@ describe('prover/bb_prover/parity', () => { // In each case either the proof should fail to generate or verify const validVk = rootParityInputs.children[0].verificationKey; - const baseParityVkPath = await getVKSiblingPath(ProtocolCircuitVkIndexes.BaseParityArtifact); + const baseParityVkPath = getVKSiblingPath(ProtocolCircuitVkIndexes.BaseParityArtifact); const validPublicInputs = rootParityInputs.children[0].publicInputs; const validProof = rootParityInputs.children[0].proof; @@ -111,7 +111,7 @@ describe('prover/bb_prover/parity', () => { validProof, validVk, baseParityVkPath, - new ParityPublicInputs(Fr.fromBuffer(shaRoot), Fr.random(), await getVKTreeRoot()), + new ParityPublicInputs(Fr.fromBuffer(shaRoot), Fr.random(), getVKTreeRoot()), ); const defectiveVerificationKey = new RootParityInput( diff --git a/yarn-project/prover-node/package.json b/yarn-project/prover-node/package.json index cc41d180e7d..70ccc7464af 100644 --- a/yarn-project/prover-node/package.json +++ b/yarn-project/prover-node/package.json @@ -63,7 +63,9 @@ "@aztec/foundation": "workspace:^", "@aztec/kv-store": "workspace:^", "@aztec/l1-artifacts": "workspace:^", + "@aztec/noir-protocol-circuits-types": "workspace:^", "@aztec/p2p": "workspace:^", + "@aztec/protocol-contracts": "workspace:^", "@aztec/prover-client": "workspace:^", "@aztec/sequencer-client": "workspace:^", "@aztec/simulator": "workspace:^", diff --git a/yarn-project/prover-node/src/config.ts b/yarn-project/prover-node/src/config.ts index dada59b55e0..97baf194498 100644 --- a/yarn-project/prover-node/src/config.ts +++ b/yarn-project/prover-node/src/config.ts @@ -131,10 +131,10 @@ export const proverNodeConfigMappings: ConfigMappingsType = { export function getProverNodeConfigFromEnv(): ProverNodeConfig { return { + ...getP2PConfigFromEnv(), ...getDataConfigFromEnv(), ...getArchiverConfigFromEnv(), ...getProverEnvVars(), - ...getP2PConfigFromEnv(), ...getWorldStateConfigFromEnv(), ...getPublisherConfigFromEnv('PROVER'), ...getTxSenderConfigFromEnv('PROVER'), diff --git a/yarn-project/prover-node/src/prover-coordination/factory.ts b/yarn-project/prover-node/src/prover-coordination/factory.ts index 6a308f0830e..47f9b03abac 100644 --- a/yarn-project/prover-node/src/prover-coordination/factory.ts +++ b/yarn-project/prover-node/src/prover-coordination/factory.ts @@ -5,11 +5,14 @@ import { type ProverCoordination, type WorldStateSynchronizer, createAztecNodeClient, + getComponentsVersionsFromConfig, } from '@aztec/circuit-types'; import { type EpochCache } from '@aztec/epoch-cache'; import { createLogger } from '@aztec/foundation/log'; import { type DataStoreConfig } from '@aztec/kv-store/config'; +import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vks'; import { createP2PClient } from '@aztec/p2p'; +import { protocolContractTreeRoot } from '@aztec/protocol-contracts'; import { type TelemetryClient, makeTracedFetch } from '@aztec/telemetry-client'; import { type ProverNodeConfig } from '../config.js'; @@ -64,7 +67,8 @@ export async function createProverCoordination( if (config.proverCoordinationNodeUrl) { log.info('Using prover coordination via node url'); - return createAztecNodeClient(config.proverCoordinationNodeUrl, makeTracedFetch([1, 2, 3], false)); + const versions = getComponentsVersionsFromConfig(config, protocolContractTreeRoot, getVKTreeRoot()); + return createAztecNodeClient(config.proverCoordinationNodeUrl, versions, makeTracedFetch([1, 2, 3], false)); } else { throw new Error(`Aztec Node URL for Tx Provider is not set.`); } diff --git a/yarn-project/prover-node/tsconfig.json b/yarn-project/prover-node/tsconfig.json index 80cf2c8db2d..bf964461484 100644 --- a/yarn-project/prover-node/tsconfig.json +++ b/yarn-project/prover-node/tsconfig.json @@ -36,9 +36,15 @@ { "path": "../l1-artifacts" }, + { + "path": "../noir-protocol-circuits-types" + }, { "path": "../p2p" }, + { + "path": "../protocol-contracts" + }, { "path": "../prover-client" }, diff --git a/yarn-project/pxe/src/bin/index.ts b/yarn-project/pxe/src/bin/index.ts index 22142b06e55..15ed46c516d 100644 --- a/yarn-project/pxe/src/bin/index.ts +++ b/yarn-project/pxe/src/bin/index.ts @@ -17,7 +17,7 @@ async function main() { logger.info(`Setting up PXE...`); const pxeConfig = getPXEServiceConfig(); - const nodeRpcClient = createAztecNodeClient(AZTEC_NODE_URL); + const nodeRpcClient = createAztecNodeClient(AZTEC_NODE_URL, {}); const pxeService = await createPXEService(nodeRpcClient, pxeConfig); const shutdown = () => { diff --git a/yarn-project/pxe/src/config/index.ts b/yarn-project/pxe/src/config/index.ts index dc971a6f30a..b2ece6595b7 100644 --- a/yarn-project/pxe/src/config/index.ts +++ b/yarn-project/pxe/src/config/index.ts @@ -1,3 +1,4 @@ +import { type ChainConfig, chainConfigMappings } from '@aztec/circuit-types/config'; import { INITIAL_L2_BLOCK_NUM } from '@aztec/circuits.js/constants'; import { type ConfigMappingsType, @@ -33,7 +34,7 @@ export interface PXEConfig { l2StartingBlock: number; } -export type PXEServiceConfig = PXEConfig & KernelProverConfig & BBProverConfig & DataStoreConfig; +export type PXEServiceConfig = PXEConfig & KernelProverConfig & BBProverConfig & DataStoreConfig & ChainConfig; export type CliPXEOptions = { /** External Aztec network to connect to. e.g. devnet */ @@ -46,6 +47,7 @@ export type CliPXEOptions = { export const pxeConfigMappings: ConfigMappingsType = { ...dataConfigMappings, + ...chainConfigMappings, l2StartingBlock: { env: 'PXE_L2_STARTING_BLOCK', ...numberConfigHelper(INITIAL_L2_BLOCK_NUM), diff --git a/yarn-project/pxe/src/kernel_oracle/index.ts b/yarn-project/pxe/src/kernel_oracle/index.ts index 6e8e67de8f1..a40fbefec5f 100644 --- a/yarn-project/pxe/src/kernel_oracle/index.ts +++ b/yarn-project/pxe/src/kernel_oracle/index.ts @@ -51,9 +51,9 @@ export class KernelOracle implements ProvingDataOracle { return await this.contractDataOracle.getFunctionMembershipWitness(contractAddress, selector); } - public async getVkMembershipWitness(vk: VerificationKeyAsFields) { - const leafIndex = await getVKIndex(vk); - return new MembershipWitness(VK_TREE_HEIGHT, BigInt(leafIndex), await getVKSiblingPath(leafIndex)); + public getVkMembershipWitness(vk: VerificationKeyAsFields) { + const leafIndex = getVKIndex(vk); + return Promise.resolve(new MembershipWitness(VK_TREE_HEIGHT, BigInt(leafIndex), getVKSiblingPath(leafIndex))); } async getNoteHashMembershipWitness(leafIndex: bigint): Promise> { diff --git a/yarn-project/pxe/src/kernel_prover/kernel_prover.ts b/yarn-project/pxe/src/kernel_prover/kernel_prover.ts index b4aad8fc7ad..66b77b1df76 100644 --- a/yarn-project/pxe/src/kernel_prover/kernel_prover.ts +++ b/yarn-project/pxe/src/kernel_prover/kernel_prover.ts @@ -214,7 +214,7 @@ export class KernelProver { if (firstIteration) { const proofInput = new PrivateKernelInitCircuitPrivateInputs( txRequest, - await getVKTreeRoot(), + getVKTreeRoot(), protocolContractTreeRoot, privateCallData, isPrivateOnlyTx, diff --git a/yarn-project/pxe/src/pxe_service/test/pxe_service.test.ts b/yarn-project/pxe/src/pxe_service/test/pxe_service.test.ts index 7284ce5c819..81cd434099e 100644 --- a/yarn-project/pxe/src/pxe_service/test/pxe_service.test.ts +++ b/yarn-project/pxe/src/pxe_service/test/pxe_service.test.ts @@ -36,6 +36,8 @@ async function createPXEService(): Promise { dataDirectory: undefined, dataStoreMapSizeKB: 1024 * 1024, l1Contracts: { rollupAddress: EthAddress.random() }, + l1ChainId: 31337, + version: 1, }; // Setup the relevant mocks @@ -87,6 +89,8 @@ describe('PXEService', () => { dataDirectory: undefined, dataStoreMapSizeKB: 1024 * 1024, l1Contracts: { rollupAddress: EthAddress.random() }, + version: 1, + l1ChainId: 31337, }; }); diff --git a/yarn-project/sequencer-client/src/config.ts b/yarn-project/sequencer-client/src/config.ts index 51e7c636244..3886e354f82 100644 --- a/yarn-project/sequencer-client/src/config.ts +++ b/yarn-project/sequencer-client/src/config.ts @@ -1,4 +1,9 @@ -import { type AllowedElement, type SequencerConfig } from '@aztec/circuit-types/config'; +import { + type AllowedElement, + type ChainConfig, + type SequencerConfig, + chainConfigMappings, +} from '@aztec/circuit-types/config'; import { AztecAddress, Fr, FunctionSelector } from '@aztec/circuits.js'; import { type L1ContractsConfig, @@ -25,14 +30,6 @@ import { export * from './publisher/config.js'; export { SequencerConfig }; -/** Chain configuration. */ -type ChainConfig = { - /** The chain id of the ethereum host. */ - l1ChainId: number; - /** The version of the rollup. */ - version: number; -}; - /** * Configuration settings for the SequencerClient. */ @@ -123,15 +120,6 @@ export const sequencerConfigMappings: ConfigMappingsType = { }, }; -export const chainConfigMappings: ConfigMappingsType = { - l1ChainId: l1ReaderConfigMappings.l1ChainId, - version: { - env: 'VERSION', - description: 'The version of the rollup.', - ...numberConfigHelper(1), - }, -}; - export const sequencerClientConfigMappings: ConfigMappingsType = { ...sequencerConfigMappings, ...l1ReaderConfigMappings, diff --git a/yarn-project/yarn.lock b/yarn-project/yarn.lock index b912118d591..6b39a551bce 100644 --- a/yarn-project/yarn.lock +++ b/yarn-project/yarn.lock @@ -96,6 +96,7 @@ __metadata: "@aztec/kv-store": "workspace:^" "@aztec/l1-artifacts": "workspace:^" "@aztec/noir-contracts.js": "workspace:^" + "@aztec/noir-protocol-circuits-types": "workspace:^" "@aztec/protocol-contracts": "workspace:^" "@aztec/telemetry-client": "workspace:^" "@aztec/types": "workspace:^" @@ -425,6 +426,7 @@ __metadata: "@aztec/entrypoints": "workspace:^" "@aztec/foundation": "workspace:^" "@aztec/noir-contracts.js": "workspace:^" + "@aztec/noir-protocol-circuits-types": "workspace:^" "@aztec/protocol-contracts": "workspace:^" "@aztec/telemetry-client": "workspace:^" "@aztec/types": "workspace:^" @@ -471,6 +473,7 @@ __metadata: "@aztec/types": "workspace:^" "@jest/globals": "npm:^29.5.0" "@types/jest": "npm:^29.5.0" + "@types/koa": "npm:^2.15.0" "@types/lodash.clonedeep": "npm:^4.5.7" "@types/lodash.isequal": "npm:^4.5.6" "@types/lodash.omit": "npm:^4.5.9" @@ -1039,6 +1042,8 @@ __metadata: "@aztec/epoch-cache": "workspace:^" "@aztec/foundation": "workspace:^" "@aztec/kv-store": "workspace:^" + "@aztec/noir-protocol-circuits-types": "workspace:^" + "@aztec/protocol-contracts": "workspace:^" "@aztec/telemetry-client": "workspace:^" "@chainsafe/discv5": "npm:9.0.0" "@chainsafe/enr": "npm:3.0.0" @@ -1176,7 +1181,9 @@ __metadata: "@aztec/foundation": "workspace:^" "@aztec/kv-store": "workspace:^" "@aztec/l1-artifacts": "workspace:^" + "@aztec/noir-protocol-circuits-types": "workspace:^" "@aztec/p2p": "workspace:^" + "@aztec/protocol-contracts": "workspace:^" "@aztec/prover-client": "workspace:^" "@aztec/sequencer-client": "workspace:^" "@aztec/simulator": "workspace:^" From 67aec61665aa554527969c85fd6e7d23d9f41bf8 Mon Sep 17 00:00:00 2001 From: Facundo Date: Fri, 7 Feb 2025 12:00:19 +0000 Subject: [PATCH 3/4] feat(avm): add skippable condition for interactions (#11800) VM1 sumcheck (16 threads) goes from `60s` to `40s`. --- .../avm/generated/relations/lookups_alu.hpp | 10 +++ .../generated/relations/lookups_binary.hpp | 10 +++ .../avm/generated/relations/lookups_gas.hpp | 25 +++++++ .../avm/generated/relations/lookups_main.hpp | 10 +++ .../avm/generated/relations/lookups_mem.hpp | 15 +++++ .../generated/relations/lookups_mem_slice.hpp | 10 +++ .../relations/lookups_range_check.hpp | 50 ++++++++++++++ .../vm/avm/generated/relations/perms_alu.hpp | 10 +++ .../vm/avm/generated/relations/perms_cmp.hpp | 15 +++++ .../vm/avm/generated/relations/perms_main.hpp | 65 +++++++++++++++++++ .../generated/relations/perms_mem_slice.hpp | 5 ++ .../generated/relations/perms_merkle_tree.hpp | 5 ++ .../generated/relations/perms_poseidon2.hpp | 40 ++++++++++++ .../relations/perms_poseidon2_full.hpp | 5 ++ .../relations/lookups_bc_decomposition.hpp | 10 +++ .../generated/relations/lookups_bitwise.hpp | 10 +++ .../generated/relations/lookups_execution.hpp | 10 +++ .../relations/lookups_range_check.hpp | 50 ++++++++++++++ .../generated/relations/lookups_sha256.hpp | 5 ++ .../generated/relations/perms_execution.hpp | 5 ++ .../bb-pil-backend/templates/lookup.hpp.hbs | 7 ++ .../templates/permutation.hpp.hbs | 6 ++ 22 files changed, 378 insertions(+) diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/lookups_alu.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/lookups_alu.hpp index c656066f1fa..47bcd8eb5fc 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/lookups_alu.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/lookups_alu.hpp @@ -75,6 +75,11 @@ template class lookup_pow_2_0_relation : public GenericLookupRelation { public: static constexpr std::string_view NAME = lookup_pow_2_0_lookup_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.alu_sel_shift_which.is_zero() && in.main_sel_rng_8.is_zero(); + } }; template using lookup_pow_2_0 = GenericLookup; @@ -144,6 +149,11 @@ template class lookup_pow_2_1_relation : public GenericLookupRelation { public: static constexpr std::string_view NAME = lookup_pow_2_1_lookup_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.alu_sel_shift_which.is_zero() && in.main_sel_rng_8.is_zero(); + } }; template using lookup_pow_2_1 = GenericLookup; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/lookups_binary.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/lookups_binary.hpp index 5588c1f1c29..8bf8f85f16f 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/lookups_binary.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/lookups_binary.hpp @@ -76,6 +76,11 @@ template class lookup_byte_lengths_relation : public GenericLookupRelation { public: static constexpr std::string_view NAME = lookup_byte_lengths_lookup_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.binary_start.is_zero() && in.byte_lookup_sel_bin.is_zero(); + } }; template using lookup_byte_lengths = GenericLookup; @@ -152,6 +157,11 @@ template class lookup_byte_operations_relation : public GenericLookupRelation { public: static constexpr std::string_view NAME = lookup_byte_operations_lookup_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.binary_sel_bin.is_zero() && in.byte_lookup_sel_bin.is_zero(); + } }; template using lookup_byte_operations = GenericLookup; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/lookups_gas.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/lookups_gas.hpp index e6a0e3f6459..dd728854f44 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/lookups_gas.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/lookups_gas.hpp @@ -88,6 +88,11 @@ template class lookup_opcode_gas_relation : public GenericLookupRelation { public: static constexpr std::string_view NAME = lookup_opcode_gas_lookup_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.main_is_gas_accounted.is_zero() && in.gas_sel_gas_cost.is_zero(); + } }; template using lookup_opcode_gas = GenericLookup; @@ -153,6 +158,11 @@ template class lookup_l2_gas_rng_chk_0_relation : public GenericLookupRelation { public: static constexpr std::string_view NAME = lookup_l2_gas_rng_chk_0_lookup_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.main_is_gas_accounted.is_zero() && in.main_sel_rng_16.is_zero(); + } }; template using lookup_l2_gas_rng_chk_0 = GenericLookup; @@ -218,6 +228,11 @@ template class lookup_l2_gas_rng_chk_1_relation : public GenericLookupRelation { public: static constexpr std::string_view NAME = lookup_l2_gas_rng_chk_1_lookup_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.main_is_gas_accounted.is_zero() && in.main_sel_rng_16.is_zero(); + } }; template using lookup_l2_gas_rng_chk_1 = GenericLookup; @@ -283,6 +298,11 @@ template class lookup_da_gas_rng_chk_0_relation : public GenericLookupRelation { public: static constexpr std::string_view NAME = lookup_da_gas_rng_chk_0_lookup_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.main_is_gas_accounted.is_zero() && in.main_sel_rng_16.is_zero(); + } }; template using lookup_da_gas_rng_chk_0 = GenericLookup; @@ -348,6 +368,11 @@ template class lookup_da_gas_rng_chk_1_relation : public GenericLookupRelation { public: static constexpr std::string_view NAME = lookup_da_gas_rng_chk_1_lookup_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.main_is_gas_accounted.is_zero() && in.main_sel_rng_16.is_zero(); + } }; template using lookup_da_gas_rng_chk_1 = GenericLookup; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/lookups_main.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/lookups_main.hpp index 710314a0aa8..d63bdf37315 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/lookups_main.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/lookups_main.hpp @@ -72,6 +72,11 @@ template class incl_main_tag_err_relation : public GenericLookupRelation { public: static constexpr std::string_view NAME = incl_main_tag_err_lookup_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.mem_tag_err.is_zero() && in.main_tag_err.is_zero(); + } }; template using incl_main_tag_err = GenericLookup; @@ -137,6 +142,11 @@ template class incl_mem_tag_err_relation : public GenericLookupRelation { public: static constexpr std::string_view NAME = incl_mem_tag_err_lookup_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.main_tag_err.is_zero() && in.mem_tag_err.is_zero(); + } }; template using incl_mem_tag_err = GenericLookup; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/lookups_mem.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/lookups_mem.hpp index f6e84a56449..0d0188f2dee 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/lookups_mem.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/lookups_mem.hpp @@ -72,6 +72,11 @@ template class lookup_mem_rng_chk_0_relation : public GenericLookupRelation { public: static constexpr std::string_view NAME = lookup_mem_rng_chk_0_lookup_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.mem_sel_rng_chk.is_zero() && in.main_sel_rng_16.is_zero(); + } }; template using lookup_mem_rng_chk_0 = GenericLookup; @@ -137,6 +142,11 @@ template class lookup_mem_rng_chk_1_relation : public GenericLookupRelation { public: static constexpr std::string_view NAME = lookup_mem_rng_chk_1_lookup_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.mem_sel_rng_chk.is_zero() && in.main_sel_rng_16.is_zero(); + } }; template using lookup_mem_rng_chk_1 = GenericLookup; @@ -202,6 +212,11 @@ template class lookup_mem_rng_chk_2_relation : public GenericLookupRelation { public: static constexpr std::string_view NAME = lookup_mem_rng_chk_2_lookup_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.mem_sel_rng_chk.is_zero() && in.main_sel_rng_8.is_zero(); + } }; template using lookup_mem_rng_chk_2 = GenericLookup; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/lookups_mem_slice.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/lookups_mem_slice.hpp index 2bb34fd9260..2ab6c193162 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/lookups_mem_slice.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/lookups_mem_slice.hpp @@ -75,6 +75,11 @@ template class lookup_cd_value_relation : public GenericLookupRelation { public: static constexpr std::string_view NAME = lookup_cd_value_lookup_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.slice_sel_cd_cpy.is_zero() && in.main_sel_calldata.is_zero(); + } }; template using lookup_cd_value = GenericLookup; @@ -143,6 +148,11 @@ template class lookup_ret_value_relation : public GenericLookupRelation { public: static constexpr std::string_view NAME = lookup_ret_value_lookup_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.slice_sel_return.is_zero() && in.main_sel_returndata.is_zero(); + } }; template using lookup_ret_value = GenericLookup; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/lookups_range_check.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/lookups_range_check.hpp index 847c9d9b02e..6fdf60a25f4 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/lookups_range_check.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/lookups_range_check.hpp @@ -76,6 +76,11 @@ template class lookup_rng_chk_pow_2_relation : public GenericLookupRelation { public: static constexpr std::string_view NAME = lookup_rng_chk_pow_2_lookup_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.range_check_sel_rng_chk.is_zero() && in.main_sel_rng_8.is_zero(); + } }; template using lookup_rng_chk_pow_2 = GenericLookup; @@ -141,6 +146,11 @@ template class lookup_rng_chk_diff_relation : public GenericLookupRelation { public: static constexpr std::string_view NAME = lookup_rng_chk_diff_lookup_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.range_check_sel_rng_chk.is_zero() && in.main_sel_rng_16.is_zero(); + } }; template using lookup_rng_chk_diff = GenericLookup; @@ -206,6 +216,11 @@ template class lookup_rng_chk_0_relation : public GenericLookupRelation { public: static constexpr std::string_view NAME = lookup_rng_chk_0_lookup_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.range_check_sel_lookup_0.is_zero() && in.main_sel_rng_16.is_zero(); + } }; template using lookup_rng_chk_0 = GenericLookup; @@ -271,6 +286,11 @@ template class lookup_rng_chk_1_relation : public GenericLookupRelation { public: static constexpr std::string_view NAME = lookup_rng_chk_1_lookup_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.range_check_sel_lookup_1.is_zero() && in.main_sel_rng_16.is_zero(); + } }; template using lookup_rng_chk_1 = GenericLookup; @@ -336,6 +356,11 @@ template class lookup_rng_chk_2_relation : public GenericLookupRelation { public: static constexpr std::string_view NAME = lookup_rng_chk_2_lookup_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.range_check_sel_lookup_2.is_zero() && in.main_sel_rng_16.is_zero(); + } }; template using lookup_rng_chk_2 = GenericLookup; @@ -401,6 +426,11 @@ template class lookup_rng_chk_3_relation : public GenericLookupRelation { public: static constexpr std::string_view NAME = lookup_rng_chk_3_lookup_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.range_check_sel_lookup_3.is_zero() && in.main_sel_rng_16.is_zero(); + } }; template using lookup_rng_chk_3 = GenericLookup; @@ -466,6 +496,11 @@ template class lookup_rng_chk_4_relation : public GenericLookupRelation { public: static constexpr std::string_view NAME = lookup_rng_chk_4_lookup_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.range_check_sel_lookup_4.is_zero() && in.main_sel_rng_16.is_zero(); + } }; template using lookup_rng_chk_4 = GenericLookup; @@ -531,6 +566,11 @@ template class lookup_rng_chk_5_relation : public GenericLookupRelation { public: static constexpr std::string_view NAME = lookup_rng_chk_5_lookup_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.range_check_sel_lookup_5.is_zero() && in.main_sel_rng_16.is_zero(); + } }; template using lookup_rng_chk_5 = GenericLookup; @@ -596,6 +636,11 @@ template class lookup_rng_chk_6_relation : public GenericLookupRelation { public: static constexpr std::string_view NAME = lookup_rng_chk_6_lookup_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.range_check_sel_lookup_6.is_zero() && in.main_sel_rng_16.is_zero(); + } }; template using lookup_rng_chk_6 = GenericLookup; @@ -661,6 +706,11 @@ template class lookup_rng_chk_7_relation : public GenericLookupRelation { public: static constexpr std::string_view NAME = lookup_rng_chk_7_lookup_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.range_check_sel_rng_chk.is_zero() && in.main_sel_rng_16.is_zero(); + } }; template using lookup_rng_chk_7 = GenericLookup; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/perms_alu.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/perms_alu.hpp index 939df9a1f33..c54e37ea263 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/perms_alu.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/perms_alu.hpp @@ -62,6 +62,11 @@ template class perm_rng_alu_relation : public GenericPermutationRelation { public: static constexpr std::string_view NAME = perm_rng_alu_permutation_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.range_check_alu_rng_chk.is_zero() && in.alu_range_check_sel.is_zero(); + } }; template using perm_rng_alu = GenericPermutation; @@ -133,6 +138,11 @@ template class perm_cmp_alu_relation : public GenericPermutationRelation { public: static constexpr std::string_view NAME = perm_cmp_alu_permutation_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.cmp_sel_cmp.is_zero() && in.alu_cmp_gadget_sel.is_zero(); + } }; template using perm_cmp_alu = GenericPermutation; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/perms_cmp.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/perms_cmp.hpp index efea46aa744..ed212855959 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/perms_cmp.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/perms_cmp.hpp @@ -58,6 +58,11 @@ template class perm_rng_non_ff_cmp_relation : public GenericPermutationRelation { public: static constexpr std::string_view NAME = perm_rng_non_ff_cmp_permutation_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.range_check_cmp_non_ff_rng_chk.is_zero() && in.cmp_op_non_ff_gt.is_zero(); + } }; template using perm_rng_non_ff_cmp = GenericPermutation; @@ -109,6 +114,11 @@ template class perm_rng_cmp_lo_relation : public GenericPermutationRelation { public: static constexpr std::string_view NAME = perm_rng_cmp_lo_permutation_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.range_check_cmp_lo_bits_rng_chk.is_zero() && in.cmp_sel_rng_chk.is_zero(); + } }; template using perm_rng_cmp_lo = GenericPermutation; @@ -160,6 +170,11 @@ template class perm_rng_cmp_hi_relation : public GenericPermutationRelation { public: static constexpr std::string_view NAME = perm_rng_cmp_hi_permutation_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.range_check_cmp_hi_bits_rng_chk.is_zero() && in.cmp_sel_rng_chk.is_zero(); + } }; template using perm_rng_cmp_hi = GenericPermutation; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/perms_main.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/perms_main.hpp index 56773a935ec..b88a0b4e05d 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/perms_main.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/perms_main.hpp @@ -114,6 +114,11 @@ template class perm_main_alu_relation : public GenericPermutationRelation { public: static constexpr std::string_view NAME = perm_main_alu_permutation_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.main_sel_alu.is_zero() && in.alu_sel_alu.is_zero(); + } }; template using perm_main_alu = GenericPermutation; @@ -181,6 +186,11 @@ template class perm_main_bin_relation : public GenericPermutationRelation { public: static constexpr std::string_view NAME = perm_main_bin_permutation_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.main_sel_bin.is_zero() && in.binary_start.is_zero(); + } }; template using perm_main_bin = GenericPermutation; @@ -244,6 +254,11 @@ template class perm_main_conv_relation : public GenericPermutationRelation { public: static constexpr std::string_view NAME = perm_main_conv_permutation_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.main_sel_op_radix_be.is_zero() && in.conversion_sel_to_radix_be.is_zero(); + } }; template using perm_main_conv = GenericPermutation; @@ -303,6 +318,11 @@ template class perm_main_sha256_relation : public GenericPermutationRelation { public: static constexpr std::string_view NAME = perm_main_sha256_permutation_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.main_sel_op_sha256.is_zero() && in.sha256_sel_sha256_compression.is_zero(); + } }; template using perm_main_sha256 = GenericPermutation; @@ -362,6 +382,11 @@ template class perm_main_pos2_perm_relation : public GenericPermutationRelation { public: static constexpr std::string_view NAME = perm_main_pos2_perm_permutation_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.main_sel_op_poseidon2.is_zero() && in.poseidon2_sel_poseidon_perm.is_zero(); + } }; template using perm_main_pos2_perm = GenericPermutation; @@ -437,6 +462,11 @@ template class perm_main_mem_a_relation : public GenericPermutationRelation { public: static constexpr std::string_view NAME = perm_main_mem_a_permutation_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.main_sel_mem_op_a.is_zero() && in.mem_sel_op_a.is_zero(); + } }; template using perm_main_mem_a = GenericPermutation; @@ -512,6 +542,11 @@ template class perm_main_mem_b_relation : public GenericPermutationRelation { public: static constexpr std::string_view NAME = perm_main_mem_b_permutation_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.main_sel_mem_op_b.is_zero() && in.mem_sel_op_b.is_zero(); + } }; template using perm_main_mem_b = GenericPermutation; @@ -583,6 +618,11 @@ template class perm_main_mem_c_relation : public GenericPermutationRelation { public: static constexpr std::string_view NAME = perm_main_mem_c_permutation_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.main_sel_mem_op_c.is_zero() && in.mem_sel_op_c.is_zero(); + } }; template using perm_main_mem_c = GenericPermutation; @@ -654,6 +694,11 @@ template class perm_main_mem_d_relation : public GenericPermutationRelation { public: static constexpr std::string_view NAME = perm_main_mem_d_permutation_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.main_sel_mem_op_d.is_zero() && in.mem_sel_op_d.is_zero(); + } }; template using perm_main_mem_d = GenericPermutation; @@ -714,6 +759,11 @@ class perm_main_mem_ind_addr_a_relation : public GenericPermutationRelation { public: static constexpr std::string_view NAME = perm_main_mem_ind_addr_a_permutation_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.main_sel_resolve_ind_addr_a.is_zero() && in.mem_sel_resolve_ind_addr_a.is_zero(); + } }; template using perm_main_mem_ind_addr_a = GenericPermutation; @@ -775,6 +825,11 @@ class perm_main_mem_ind_addr_b_relation : public GenericPermutationRelation { public: static constexpr std::string_view NAME = perm_main_mem_ind_addr_b_permutation_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.main_sel_resolve_ind_addr_b.is_zero() && in.mem_sel_resolve_ind_addr_b.is_zero(); + } }; template using perm_main_mem_ind_addr_b = GenericPermutation; @@ -836,6 +891,11 @@ class perm_main_mem_ind_addr_c_relation : public GenericPermutationRelation { public: static constexpr std::string_view NAME = perm_main_mem_ind_addr_c_permutation_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.main_sel_resolve_ind_addr_c.is_zero() && in.mem_sel_resolve_ind_addr_c.is_zero(); + } }; template using perm_main_mem_ind_addr_c = GenericPermutation; @@ -897,6 +957,11 @@ class perm_main_mem_ind_addr_d_relation : public GenericPermutationRelation { public: static constexpr std::string_view NAME = perm_main_mem_ind_addr_d_permutation_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.main_sel_resolve_ind_addr_d.is_zero() && in.mem_sel_resolve_ind_addr_d.is_zero(); + } }; template using perm_main_mem_ind_addr_d = GenericPermutation; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/perms_mem_slice.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/perms_mem_slice.hpp index 72e79b2a55c..c8865f513de 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/perms_mem_slice.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/perms_mem_slice.hpp @@ -70,6 +70,11 @@ template class perm_slice_mem_relation : public GenericPermutationRelation { public: static constexpr std::string_view NAME = perm_slice_mem_permutation_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.slice_sel_mem_active.is_zero() && in.mem_sel_op_slice.is_zero(); + } }; template using perm_slice_mem = GenericPermutation; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/perms_merkle_tree.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/perms_merkle_tree.hpp index 8364b26afb2..6b964614972 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/perms_merkle_tree.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/perms_merkle_tree.hpp @@ -67,6 +67,11 @@ class perm_merkle_poseidon2_relation : public GenericPermutationRelation { public: static constexpr std::string_view NAME = perm_merkle_poseidon2_permutation_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.merkle_tree_sel_merkle_tree.is_zero() && in.poseidon2_full_sel_merkle_tree.is_zero(); + } }; template using perm_merkle_poseidon2 = GenericPermutation; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/perms_poseidon2.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/perms_poseidon2.hpp index 71186c8d965..f0136a3045a 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/perms_poseidon2.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/perms_poseidon2.hpp @@ -70,6 +70,11 @@ template class perm_pos_mem_read_a_relation : public GenericPermutationRelation { public: static constexpr std::string_view NAME = perm_pos_mem_read_a_permutation_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.poseidon2_sel_poseidon_perm_mem_op.is_zero() && in.mem_sel_op_poseidon_read_a.is_zero(); + } }; template using perm_pos_mem_read_a = GenericPermutation; @@ -133,6 +138,11 @@ template class perm_pos_mem_read_b_relation : public GenericPermutationRelation { public: static constexpr std::string_view NAME = perm_pos_mem_read_b_permutation_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.poseidon2_sel_poseidon_perm_mem_op.is_zero() && in.mem_sel_op_poseidon_read_b.is_zero(); + } }; template using perm_pos_mem_read_b = GenericPermutation; @@ -196,6 +206,11 @@ template class perm_pos_mem_read_c_relation : public GenericPermutationRelation { public: static constexpr std::string_view NAME = perm_pos_mem_read_c_permutation_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.poseidon2_sel_poseidon_perm_mem_op.is_zero() && in.mem_sel_op_poseidon_read_c.is_zero(); + } }; template using perm_pos_mem_read_c = GenericPermutation; @@ -259,6 +274,11 @@ template class perm_pos_mem_read_d_relation : public GenericPermutationRelation { public: static constexpr std::string_view NAME = perm_pos_mem_read_d_permutation_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.poseidon2_sel_poseidon_perm_mem_op.is_zero() && in.mem_sel_op_poseidon_read_d.is_zero(); + } }; template using perm_pos_mem_read_d = GenericPermutation; @@ -323,6 +343,11 @@ class perm_pos_mem_write_a_relation : public GenericPermutationRelation { public: static constexpr std::string_view NAME = perm_pos_mem_write_a_permutation_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.poseidon2_sel_poseidon_perm_mem_op.is_zero() && in.mem_sel_op_poseidon_write_a.is_zero(); + } }; template using perm_pos_mem_write_a = GenericPermutation; @@ -387,6 +412,11 @@ class perm_pos_mem_write_b_relation : public GenericPermutationRelation { public: static constexpr std::string_view NAME = perm_pos_mem_write_b_permutation_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.poseidon2_sel_poseidon_perm_mem_op.is_zero() && in.mem_sel_op_poseidon_write_b.is_zero(); + } }; template using perm_pos_mem_write_b = GenericPermutation; @@ -451,6 +481,11 @@ class perm_pos_mem_write_c_relation : public GenericPermutationRelation { public: static constexpr std::string_view NAME = perm_pos_mem_write_c_permutation_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.poseidon2_sel_poseidon_perm_mem_op.is_zero() && in.mem_sel_op_poseidon_write_c.is_zero(); + } }; template using perm_pos_mem_write_c = GenericPermutation; @@ -515,6 +550,11 @@ class perm_pos_mem_write_d_relation : public GenericPermutationRelation { public: static constexpr std::string_view NAME = perm_pos_mem_write_d_permutation_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.poseidon2_sel_poseidon_perm_mem_op.is_zero() && in.mem_sel_op_poseidon_write_d.is_zero(); + } }; template using perm_pos_mem_write_d = GenericPermutation; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/perms_poseidon2_full.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/perms_poseidon2_full.hpp index 3fcf47e3d24..983986f40f3 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/perms_poseidon2_full.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/generated/relations/perms_poseidon2_full.hpp @@ -87,6 +87,11 @@ class perm_pos2_fixed_pos2_perm_relation : public GenericPermutationRelation { public: static constexpr std::string_view NAME = perm_pos2_fixed_pos2_perm_permutation_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.poseidon2_full_sel_poseidon.is_zero() && in.poseidon2_sel_poseidon_perm_immediate.is_zero(); + } }; template using perm_pos2_fixed_pos2_perm = GenericPermutation; diff --git a/barretenberg/cpp/src/barretenberg/vm2/generated/relations/lookups_bc_decomposition.hpp b/barretenberg/cpp/src/barretenberg/vm2/generated/relations/lookups_bc_decomposition.hpp index 4e227853ad4..e6f6d10664a 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/generated/relations/lookups_bc_decomposition.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/generated/relations/lookups_bc_decomposition.hpp @@ -73,6 +73,11 @@ class lookup_bytecode_bytes_are_bytes_relation : public GenericLookupRelation { public: static constexpr std::string_view NAME = lookup_bytecode_bytes_are_bytes_lookup_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.bc_decomposition_sel.is_zero() && in.precomputed_sel_range_8.is_zero(); + } }; template using lookup_bytecode_bytes_are_bytes = GenericLookup; @@ -145,6 +150,11 @@ class lookup_bytecode_to_read_unary_relation : public GenericLookupRelation { public: static constexpr std::string_view NAME = lookup_bytecode_to_read_unary_lookup_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.bc_decomposition_sel.is_zero() && in.precomputed_sel_unary.is_zero(); + } }; template using lookup_bytecode_to_read_unary = GenericLookup; diff --git a/barretenberg/cpp/src/barretenberg/vm2/generated/relations/lookups_bitwise.hpp b/barretenberg/cpp/src/barretenberg/vm2/generated/relations/lookups_bitwise.hpp index d2bb98304cc..7e5e9f8c932 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/generated/relations/lookups_bitwise.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/generated/relations/lookups_bitwise.hpp @@ -75,6 +75,11 @@ template class lookup_bitw_byte_lengths_relation : public GenericLookupRelation { public: static constexpr std::string_view NAME = lookup_bitw_byte_lengths_lookup_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.bitwise_start.is_zero() && in.precomputed_sel_integral_tag.is_zero(); + } }; template using lookup_bitw_byte_lengths = GenericLookup; @@ -152,6 +157,11 @@ class lookup_bitw_byte_operations_relation : public GenericLookupRelation { public: static constexpr std::string_view NAME = lookup_bitw_byte_operations_lookup_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.bitwise_sel.is_zero() && in.precomputed_sel_bitwise.is_zero(); + } }; template using lookup_bitw_byte_operations = GenericLookup; diff --git a/barretenberg/cpp/src/barretenberg/vm2/generated/relations/lookups_execution.hpp b/barretenberg/cpp/src/barretenberg/vm2/generated/relations/lookups_execution.hpp index db68fe8aff2..cc655d52686 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/generated/relations/lookups_execution.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/generated/relations/lookups_execution.hpp @@ -83,6 +83,11 @@ template class lookup_dummy_precomputed_relation : public GenericLookupRelation { public: static constexpr std::string_view NAME = lookup_dummy_precomputed_lookup_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.execution_sel.is_zero() && in.precomputed_sel_bitwise.is_zero(); + } }; template using lookup_dummy_precomputed = GenericLookup; @@ -158,6 +163,11 @@ template class lookup_dummy_dynamic_relation : public GenericLookupRelation { public: static constexpr std::string_view NAME = lookup_dummy_dynamic_lookup_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.execution_sel.is_zero() && in.execution_sel.is_zero(); + } }; template using lookup_dummy_dynamic = GenericLookup; diff --git a/barretenberg/cpp/src/barretenberg/vm2/generated/relations/lookups_range_check.hpp b/barretenberg/cpp/src/barretenberg/vm2/generated/relations/lookups_range_check.hpp index d167baa29fb..5a4dbb8c534 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/generated/relations/lookups_range_check.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/generated/relations/lookups_range_check.hpp @@ -76,6 +76,11 @@ template class lookup_rng_chk_pow_2_relation : public GenericLookupRelation { public: static constexpr std::string_view NAME = lookup_rng_chk_pow_2_lookup_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.range_check_sel.is_zero() && in.precomputed_sel_range_8.is_zero(); + } }; template using lookup_rng_chk_pow_2 = GenericLookup; @@ -141,6 +146,11 @@ template class lookup_rng_chk_diff_relation : public GenericLookupRelation { public: static constexpr std::string_view NAME = lookup_rng_chk_diff_lookup_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.range_check_sel.is_zero() && in.precomputed_sel_range_16.is_zero(); + } }; template using lookup_rng_chk_diff = GenericLookup; @@ -207,6 +217,11 @@ class lookup_rng_chk_is_r0_16_bit_relation : public GenericLookupRelation { public: static constexpr std::string_view NAME = lookup_rng_chk_is_r0_16_bit_lookup_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.range_check_sel_r0_16_bit_rng_lookup.is_zero() && in.precomputed_sel_range_16.is_zero(); + } }; template using lookup_rng_chk_is_r0_16_bit = GenericLookup; @@ -274,6 +289,11 @@ class lookup_rng_chk_is_r1_16_bit_relation : public GenericLookupRelation { public: static constexpr std::string_view NAME = lookup_rng_chk_is_r1_16_bit_lookup_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.range_check_sel_r1_16_bit_rng_lookup.is_zero() && in.precomputed_sel_range_16.is_zero(); + } }; template using lookup_rng_chk_is_r1_16_bit = GenericLookup; @@ -341,6 +361,11 @@ class lookup_rng_chk_is_r2_16_bit_relation : public GenericLookupRelation { public: static constexpr std::string_view NAME = lookup_rng_chk_is_r2_16_bit_lookup_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.range_check_sel_r2_16_bit_rng_lookup.is_zero() && in.precomputed_sel_range_16.is_zero(); + } }; template using lookup_rng_chk_is_r2_16_bit = GenericLookup; @@ -408,6 +433,11 @@ class lookup_rng_chk_is_r3_16_bit_relation : public GenericLookupRelation { public: static constexpr std::string_view NAME = lookup_rng_chk_is_r3_16_bit_lookup_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.range_check_sel_r3_16_bit_rng_lookup.is_zero() && in.precomputed_sel_range_16.is_zero(); + } }; template using lookup_rng_chk_is_r3_16_bit = GenericLookup; @@ -475,6 +505,11 @@ class lookup_rng_chk_is_r4_16_bit_relation : public GenericLookupRelation { public: static constexpr std::string_view NAME = lookup_rng_chk_is_r4_16_bit_lookup_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.range_check_sel_r4_16_bit_rng_lookup.is_zero() && in.precomputed_sel_range_16.is_zero(); + } }; template using lookup_rng_chk_is_r4_16_bit = GenericLookup; @@ -542,6 +577,11 @@ class lookup_rng_chk_is_r5_16_bit_relation : public GenericLookupRelation { public: static constexpr std::string_view NAME = lookup_rng_chk_is_r5_16_bit_lookup_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.range_check_sel_r5_16_bit_rng_lookup.is_zero() && in.precomputed_sel_range_16.is_zero(); + } }; template using lookup_rng_chk_is_r5_16_bit = GenericLookup; @@ -609,6 +649,11 @@ class lookup_rng_chk_is_r6_16_bit_relation : public GenericLookupRelation { public: static constexpr std::string_view NAME = lookup_rng_chk_is_r6_16_bit_lookup_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.range_check_sel_r6_16_bit_rng_lookup.is_zero() && in.precomputed_sel_range_16.is_zero(); + } }; template using lookup_rng_chk_is_r6_16_bit = GenericLookup; @@ -676,6 +721,11 @@ class lookup_rng_chk_is_r7_16_bit_relation : public GenericLookupRelation { public: static constexpr std::string_view NAME = lookup_rng_chk_is_r7_16_bit_lookup_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.range_check_sel.is_zero() && in.precomputed_sel_range_16.is_zero(); + } }; template using lookup_rng_chk_is_r7_16_bit = GenericLookup; diff --git a/barretenberg/cpp/src/barretenberg/vm2/generated/relations/lookups_sha256.hpp b/barretenberg/cpp/src/barretenberg/vm2/generated/relations/lookups_sha256.hpp index c3616e3faac..5d954b5305c 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/generated/relations/lookups_sha256.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/generated/relations/lookups_sha256.hpp @@ -78,6 +78,11 @@ class lookup_sha256_round_constant_relation : public GenericLookupRelation { public: static constexpr std::string_view NAME = lookup_sha256_round_constant_lookup_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.sha256_sel.is_zero() && in.precomputed_sel_sha256_compression.is_zero(); + } }; template using lookup_sha256_round_constant = GenericLookup; diff --git a/barretenberg/cpp/src/barretenberg/vm2/generated/relations/perms_execution.hpp b/barretenberg/cpp/src/barretenberg/vm2/generated/relations/perms_execution.hpp index 34375bbcdda..010245c343f 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/generated/relations/perms_execution.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/generated/relations/perms_execution.hpp @@ -66,6 +66,11 @@ template class perm_dummy_dynamic_relation : public GenericPermutationRelation { public: static constexpr std::string_view NAME = perm_dummy_dynamic_permutation_settings::NAME; + + template inline static bool skip(const AllEntities& in) + { + return in.execution_sel.is_zero() && in.execution_sel.is_zero(); + } }; template using perm_dummy_dynamic = GenericPermutation; diff --git a/bb-pilcom/bb-pil-backend/templates/lookup.hpp.hbs b/bb-pilcom/bb-pil-backend/templates/lookup.hpp.hbs index 2a6e3cb35fb..ce3f02b73e5 100644 --- a/bb-pilcom/bb-pil-backend/templates/lookup.hpp.hbs +++ b/bb-pilcom/bb-pil-backend/templates/lookup.hpp.hbs @@ -86,6 +86,13 @@ class {{lookup_name}}_lookup_settings { template class {{lookup_name}}_relation : public GenericLookupRelation<{{lookup_name}}_lookup_settings, FF_> { public: static constexpr std::string_view NAME = {{lookup_name}}_lookup_settings::NAME; + + {{! TODO: This is a safe skippable condition, but there might be a better one. --}} + template inline static bool skip(const AllEntities& in) + { + return in.{{lhs_selector}}.is_zero() && in.{{rhs_selector}}.is_zero(); + } + }; template using {{lookup_name}} = GenericLookup<{{lookup_name}}_lookup_settings, FF_>; diff --git a/bb-pilcom/bb-pil-backend/templates/permutation.hpp.hbs b/bb-pilcom/bb-pil-backend/templates/permutation.hpp.hbs index dbca55ff1d9..d17ff0a5872 100644 --- a/bb-pilcom/bb-pil-backend/templates/permutation.hpp.hbs +++ b/bb-pilcom/bb-pil-backend/templates/permutation.hpp.hbs @@ -52,6 +52,12 @@ class {{perm_name}}_permutation_settings { template class {{perm_name}}_relation : public GenericPermutationRelation<{{perm_name}}_permutation_settings, FF_> { public: static constexpr std::string_view NAME = {{perm_name}}_permutation_settings::NAME; + + {{! TODO: This is a safe skippable condition, but there might be a better one. --}} + template inline static bool skip(const AllEntities& in) + { + return in.{{lhs_selector}}.is_zero() && in.{{rhs_selector}}.is_zero(); + } }; template using {{perm_name}} = GenericPermutation<{{perm_name}}_permutation_settings, FF_>; From ee5fc45d1347fd12d924efd4e9a2305ba5efe5b7 Mon Sep 17 00:00:00 2001 From: guipublic <47281315+guipublic@users.noreply.github.com> Date: Fri, 7 Feb 2025 13:01:24 +0100 Subject: [PATCH 4/4] chore: do not differentiate variable vs fixed length for Poseidon2 (#11740) Remove the terminator for poseidon2 that was used to distinguish between fixed and variable size hashes. --- .../crypto/poseidon2/poseidon2.cpp | 2 +- .../crypto/poseidon2/sponge/sponge.hpp | 23 ++------------- .../stdlib/hash/poseidon2/poseidon2.cpp | 2 +- .../stdlib/hash/poseidon2/sponge/sponge.hpp | 28 ++----------------- 4 files changed, 7 insertions(+), 48 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2.cpp b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2.cpp index dad8ea1d3b1..bb2f920a152 100644 --- a/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2.cpp +++ b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2.cpp @@ -7,7 +7,7 @@ namespace bb::crypto { template typename Poseidon2::FF Poseidon2::hash(const std::vector::FF>& input) { - return Sponge::hash_fixed_length(input); + return Sponge::hash_internal(input); } /** diff --git a/barretenberg/cpp/src/barretenberg/crypto/poseidon2/sponge/sponge.hpp b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/sponge/sponge.hpp index eb89c96e471..72324c2654b 100644 --- a/barretenberg/cpp/src/barretenberg/crypto/poseidon2/sponge/sponge.hpp +++ b/barretenberg/cpp/src/barretenberg/crypto/poseidon2/sponge/sponge.hpp @@ -125,12 +125,10 @@ template */ - template - static std::array hash_internal(std::span input) + template static std::array hash_internal(std::span input) { size_t in_len = input.size(); const uint256_t iv = (static_cast(in_len) << 64) + out_len - 1; @@ -140,13 +138,6 @@ template output; for (size_t i = 0; i < out_len; ++i) { output[i] = sponge.squeeze(); @@ -154,16 +145,6 @@ template static std::array hash_fixed_length(std::span input) - { - return hash_internal(input); - } - static FF hash_fixed_length(std::span input) { return hash_fixed_length<1>(input)[0]; } - - template static std::array hash_variable_length(std::span input) - { - return hash_internal(input); - } - static FF hash_variable_length(std::span input) { return hash_variable_length<1>(input)[0]; } + static FF hash_internal(std::span input) { return hash_internal<1>(input)[0]; } }; } // namespace bb::crypto \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/stdlib/hash/poseidon2/poseidon2.cpp b/barretenberg/cpp/src/barretenberg/stdlib/hash/poseidon2/poseidon2.cpp index 82aa0ffc054..2e41a8ceae8 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/hash/poseidon2/poseidon2.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/hash/poseidon2/poseidon2.cpp @@ -14,7 +14,7 @@ template field_t poseidon2::hash(C& builder, const std::vecto * This should just call the sponge variable length hash function * */ - return Sponge::hash_fixed_length(builder, inputs); + return Sponge::hash_internal(builder, inputs); } /** diff --git a/barretenberg/cpp/src/barretenberg/stdlib/hash/poseidon2/sponge/sponge.hpp b/barretenberg/cpp/src/barretenberg/stdlib/hash/poseidon2/sponge/sponge.hpp index a812ec7811e..72d9df6cd35 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/hash/poseidon2/sponge/sponge.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/hash/poseidon2/sponge/sponge.hpp @@ -134,7 +134,7 @@ template */ - template + template static std::array hash_internal(Builder& builder, std::span input) { size_t in_len = input.size(); @@ -145,13 +145,6 @@ template output; for (size_t i = 0; i < out_len; ++i) { output[i] = sponge.squeeze(); @@ -159,24 +152,9 @@ template - static std::array hash_fixed_length(Builder& builder, std::span input) - { - return hash_internal(builder, input); - } - static field_t hash_fixed_length(Builder& builder, std::span input) - { - return hash_fixed_length<1>(builder, input)[0]; - } - - template - static std::array hash_variable_length(Builder& builder, std::span input) - { - return hash_internal(builder, input); - } - static field_t hash_variable_length(Builder& builder, std::span input) + static field_t hash_internal(Builder& builder, std::span input) { - return hash_variable_length<1>(builder, input)[0]; + return hash_internal<1>(builder, input)[0]; } }; } // namespace bb::stdlib \ No newline at end of file