Skip to content

Commit b33f1da

Browse files
spalladinoMaddiaa0
andauthored
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 <[email protected]>
1 parent baa69a2 commit b33f1da

File tree

89 files changed

+1136
-411
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

89 files changed

+1136
-411
lines changed

spartan/aztec-network/templates/pxe.yaml

+2
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@ spec:
113113
value: "{{ .Values.telemetry.useGcloudObservability }}"
114114
- name: OTEL_EXCLUDE_METRICS
115115
value: "{{ .Values.telemetry.excludeMetrics }}"
116+
- name: L1_CHAIN_ID
117+
value: "{{ .Values.ethereum.chainId }}"
116118
ports:
117119
- name: http
118120
containerPort: {{ .Values.pxe.service.nodePort }}

spartan/aztec-network/templates/transaction-bot.yaml

+2
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,8 @@ spec:
135135
value: "{{ .Values.telemetry.useGcloudObservability }}"
136136
- name: OTEL_EXCLUDE_METRICS
137137
value: "{{ .Values.telemetry.excludeMetrics }}"
138+
- name: L1_CHAIN_ID
139+
value: "{{ .Values.ethereum.chainId }}"
138140
ports:
139141
- name: http
140142
containerPort: {{ .Values.bot.service.nodePort }}

yarn-project/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ noir-protocol-circuits-types/src/private_kernel_reset_data.ts
4141
noir-protocol-circuits-types/src/private_kernel_reset_vks.ts
4242
noir-protocol-circuits-types/src/private_kernel_reset_types.ts
4343
noir-protocol-circuits-types/src/client_artifacts_helper.ts
44+
noir-protocol-circuits-types/src/vk_tree.ts
4445
noir-protocol-circuits-types/src/types/
4546
ivc-integration/artifacts
4647
ivc-integration/src/types/

yarn-project/archiver/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373
"@aztec/kv-store": "workspace:^",
7474
"@aztec/l1-artifacts": "workspace:^",
7575
"@aztec/noir-contracts.js": "workspace:^",
76+
"@aztec/noir-protocol-circuits-types": "workspace:^",
7677
"@aztec/protocol-contracts": "workspace:^",
7778
"@aztec/telemetry-client": "workspace:^",
7879
"@aztec/types": "workspace:^",

yarn-project/archiver/src/archiver/config.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { type ChainConfig, chainConfigMappings } from '@aztec/circuit-types/config';
12
import {
23
type L1ContractAddresses,
34
type L1ContractsConfig,
@@ -39,7 +40,8 @@ export type ArchiverConfig = {
3940
/** The max number of logs that can be obtained in 1 "getPublicLogs" call. */
4041
maxLogs?: number;
4142
} & L1ReaderConfig &
42-
L1ContractsConfig;
43+
L1ContractsConfig &
44+
ChainConfig;
4345

4446
export const archiverConfigMappings: ConfigMappingsType<ArchiverConfig> = {
4547
archiverUrl: {
@@ -67,6 +69,7 @@ export const archiverConfigMappings: ConfigMappingsType<ArchiverConfig> = {
6769
description: 'The max number of logs that can be obtained in 1 "getPublicLogs" call.',
6870
...numberConfigHelper(1_000),
6971
},
72+
...chainConfigMappings,
7073
...l1ReaderConfigMappings,
7174
viemPollingIntervalMS: {
7275
env: 'ARCHIVER_VIEM_POLLING_INTERVAL_MS',

yarn-project/archiver/src/factory.ts

+7-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { type BlobSinkClientInterface } from '@aztec/blob-sink/client';
2-
import { type ArchiverApi, type Service } from '@aztec/circuit-types';
2+
import { type ArchiverApi, type Service, getComponentsVersionsFromConfig } from '@aztec/circuit-types';
33
import {
44
type ContractClassPublic,
55
computePublicBytecodeCommitment,
@@ -12,7 +12,8 @@ import { type DataStoreConfig } from '@aztec/kv-store/config';
1212
import { createStore } from '@aztec/kv-store/lmdb-v2';
1313
import { TokenContractArtifact } from '@aztec/noir-contracts.js/Token';
1414
import { TokenBridgeContractArtifact } from '@aztec/noir-contracts.js/TokenBridge';
15-
import { protocolContractNames } from '@aztec/protocol-contracts';
15+
import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vks';
16+
import { protocolContractNames, protocolContractTreeRoot } from '@aztec/protocol-contracts';
1617
import { getCanonicalProtocolContract } from '@aztec/protocol-contracts/bundle';
1718
import { type TelemetryClient, getTelemetryClient } from '@aztec/telemetry-client';
1819

@@ -34,7 +35,10 @@ export async function createArchiver(
3435
await registerCommonContracts(archiverStore);
3536
return Archiver.createAndSync(config, archiverStore, { telemetry, blobSinkClient }, opts.blockUntilSync);
3637
} else {
37-
return createArchiverClient(config.archiverUrl);
38+
return createArchiverClient(
39+
config.archiverUrl,
40+
getComponentsVersionsFromConfig(config, protocolContractTreeRoot, getVKTreeRoot()),
41+
);
3842
}
3943
}
4044

yarn-project/archiver/src/rpc/index.ts

+16-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,22 @@
1-
import { type ArchiverApi, ArchiverApiSchema } from '@aztec/circuit-types';
1+
import {
2+
type ArchiverApi,
3+
ArchiverApiSchema,
4+
type ComponentsVersions,
5+
getVersioningResponseHandler,
6+
} from '@aztec/circuit-types';
27
import { createSafeJsonRpcClient } from '@aztec/foundation/json-rpc/client';
38
import { createTracedJsonRpcServer, makeTracedFetch } from '@aztec/telemetry-client';
49

5-
export function createArchiverClient(url: string, fetch = makeTracedFetch([1, 2, 3], true)): ArchiverApi {
6-
return createSafeJsonRpcClient<ArchiverApi>(url, ArchiverApiSchema, false, 'archiver', fetch);
10+
export function createArchiverClient(
11+
url: string,
12+
versions: Partial<ComponentsVersions>,
13+
fetch = makeTracedFetch([1, 2, 3], true),
14+
): ArchiverApi {
15+
return createSafeJsonRpcClient<ArchiverApi>(url, ArchiverApiSchema, {
16+
namespaceMethods: 'archiver',
17+
fetch,
18+
onResponse: getVersioningResponseHandler(versions),
19+
});
720
}
821

922
export function createArchiverRpcServer(handler: ArchiverApi) {

yarn-project/archiver/tsconfig.json

+3
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@
3333
{
3434
"path": "../noir-contracts.js"
3535
},
36+
{
37+
"path": "../noir-protocol-circuits-types"
38+
},
3639
{
3740
"path": "../protocol-contracts"
3841
},

yarn-project/aztec-node/src/aztec-node/server.ts

-5
Original file line numberDiff line numberDiff line change
@@ -164,11 +164,6 @@ export class AztecNodeService implements AztecNode, Traceable {
164164

165165
const archiver = await createArchiver(config, blobSinkClient, { blockUntilSync: true }, telemetry);
166166

167-
// we identify the P2P transaction protocol by using the rollup contract address.
168-
// this may well change in future
169-
const rollupAddress = config.l1Contracts.rollupAddress;
170-
config.transactionProtocol = `/aztec/tx/${rollupAddress.toString()}`;
171-
172167
// now create the merkle trees and the world state synchronizer
173168
const worldStateSynchronizer = await createWorldStateSynchronizer(config, archiver, telemetry);
174169
const proofVerifier = config.realProofs ? await BBCircuitVerifier.new(config) : new TestCircuitVerifier();

yarn-project/aztec.js/src/api/ethereum/l1_contracts.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { retryUntil } from '@aztec/foundation/retry';
44
import { createPXEClient } from '../../rpc_clients/index.js';
55

66
export const getL1ContractAddresses = async (url: string): Promise<L1ContractAddresses> => {
7-
const pxeClient = createPXEClient(url);
7+
const pxeClient = createPXEClient(url, {});
88
const response = await retryUntil(
99
async () => {
1010
try {

yarn-project/aztec.js/src/rpc_clients/node/index.ts

+14-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import { type PXE } from '@aztec/circuit-types';
1+
import { type ComponentsVersions, type PXE } from '@aztec/circuit-types';
22
import { jsonStringify } from '@aztec/foundation/json-rpc';
3-
import { type Logger } from '@aztec/foundation/log';
3+
import { type Logger, createLogger } from '@aztec/foundation/log';
44
import { NoRetryError, makeBackoff, retry } from '@aztec/foundation/retry';
55

66
import { Axios, type AxiosError } from 'axios';
@@ -33,9 +33,13 @@ async function axiosFetch(host: string, rpcMethod: string, body: any, useApiEndp
3333

3434
const isOK = resp.status >= 200 && resp.status < 300;
3535
if (isOK) {
36-
return resp.data;
36+
const headers = {
37+
get: (header: string) =>
38+
typeof resp.headers.get === 'function' ? resp.headers.get(header)?.toString() : undefined,
39+
};
40+
return { response: resp.data, headers };
3741
} else {
38-
const errorMessage = `(JSON-RPC PROPAGATED) (host ${host}) (method ${rpcMethod}) (code ${resp.status}) ${resp.data.error.message}`;
42+
const errorMessage = `Error ${resp.status} from json-rpc server ${host} on ${rpcMethod}: ${resp.data.error.message}`;
3943
if (resp.status >= 400 && resp.status < 500) {
4044
throw new NoRetryError(errorMessage);
4145
} else {
@@ -51,7 +55,11 @@ async function axiosFetch(host: string, rpcMethod: string, body: any, useApiEndp
5155
* @param _logger - Debug logger to warn version incompatibilities.
5256
* @returns A PXE client.
5357
*/
54-
export function createCompatibleClient(rpcUrl: string, logger: Logger): Promise<PXE> {
58+
export function createCompatibleClient(
59+
rpcUrl: string,
60+
logger: Logger = createLogger('aztecjs:pxe_client'),
61+
versions: Partial<ComponentsVersions> = {},
62+
): Promise<PXE> {
5563
// Use axios due to timeout issues with fetch when proving TXs.
5664
const fetch = async (host: string, rpcMethod: string, body: any, useApiEndpoints: boolean) => {
5765
return await retry(
@@ -62,7 +70,7 @@ export function createCompatibleClient(rpcUrl: string, logger: Logger): Promise<
6270
false,
6371
);
6472
};
65-
const pxe = createPXEClient(rpcUrl, fetch);
73+
const pxe = createPXEClient(rpcUrl, versions, fetch);
6674

6775
return Promise.resolve(pxe);
6876
}
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,25 @@
1+
import { type ComponentsVersions, getVersioningResponseHandler } from '@aztec/circuit-types';
12
import { type PXE, PXESchema } from '@aztec/circuit-types/interfaces';
23
import { createSafeJsonRpcClient, makeFetch } from '@aztec/foundation/json-rpc/client';
4+
import { protocolContractTreeRoot } from '@aztec/protocol-contracts';
35

46
/**
57
* Creates a JSON-RPC client to remotely talk to PXE.
68
* @param url - The URL of the PXE.
79
* @param fetch - The fetch implementation to use.
810
* @returns A JSON-RPC client of PXE.
911
*/
10-
export function createPXEClient(url: string, fetch = makeFetch([1, 2, 3], false)): PXE {
11-
return createSafeJsonRpcClient<PXE>(url, PXESchema, false, 'pxe', fetch);
12+
export function createPXEClient(
13+
url: string,
14+
versions: Partial<ComponentsVersions> = {},
15+
fetch = makeFetch([1, 2, 3], false),
16+
): PXE {
17+
return createSafeJsonRpcClient<PXE>(url, PXESchema, {
18+
namespaceMethods: 'pxe',
19+
fetch,
20+
onResponse: getVersioningResponseHandler({
21+
l2ProtocolContractsTreeRoot: protocolContractTreeRoot.toString(),
22+
...versions,
23+
}),
24+
});
1225
}

yarn-project/aztec/src/cli/aztec_start_action.ts

+12-9
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { deployInitialTestAccounts } from '@aztec/accounts/testing';
2-
import { AztecNodeApiSchema, PXESchema } from '@aztec/circuit-types';
2+
import { AztecNodeApiSchema, PXESchema, getVersioningMiddleware } from '@aztec/circuit-types';
3+
import { type ChainConfig } from '@aztec/circuit-types/config';
34
import {
45
type NamespacedApiHandlers,
56
createNamespacedSafeJsonRpcServer,
@@ -15,6 +16,7 @@ import { dirname, resolve } from 'path';
1516
import { createSandbox } from '../sandbox.js';
1617
import { github, splash } from '../splash.js';
1718
import { createAccountLogs, extractNamespacedOptions, installSignalHandlers } from './util.js';
19+
import { getVersions } from './versioning.js';
1820

1921
const packageJsonPath = resolve(dirname(fileURLToPath(import.meta.url)), '../../package.json');
2022
const cliVersion: string = JSON.parse(readFileSync(packageJsonPath).toString()).version;
@@ -23,6 +25,7 @@ export async function aztecStart(options: any, userLog: LogFn, debugLogger: Logg
2325
// list of 'stop' functions to call when process ends
2426
const signalHandlers: Array<() => Promise<void>> = [];
2527
const services: NamespacedApiHandlers = {};
28+
let config: ChainConfig | undefined = undefined;
2629

2730
if (options.sandbox) {
2831
const sandboxOptions = extractNamespacedOptions(options, 'sandbox');
@@ -61,7 +64,7 @@ export async function aztecStart(options: any, userLog: LogFn, debugLogger: Logg
6164
} else {
6265
if (options.node) {
6366
const { startNode } = await import('./cmds/start_node.js');
64-
await startNode(options, signalHandlers, services, userLog);
67+
({ config } = await startNode(options, signalHandlers, services, userLog));
6568
} else if (options.proofVerifier) {
6669
const { startProofVerifier } = await import('./cmds/start_proof_verifier.js');
6770
await startProofVerifier(options, signalHandlers, userLog);
@@ -70,16 +73,16 @@ export async function aztecStart(options: any, userLog: LogFn, debugLogger: Logg
7073
await startBot(options, signalHandlers, services, userLog);
7174
} else if (options.proverNode) {
7275
const { startProverNode } = await import('./cmds/start_prover_node.js');
73-
await startProverNode(options, signalHandlers, services, userLog);
76+
({ config } = await startProverNode(options, signalHandlers, services, userLog));
7477
} else if (options.pxe) {
7578
const { startPXE } = await import('./cmds/start_pxe.js');
76-
await startPXE(options, signalHandlers, services, userLog);
79+
({ config } = await startPXE(options, signalHandlers, services, userLog));
7780
} else if (options.archiver) {
7881
const { startArchiver } = await import('./cmds/start_archiver.js');
79-
await startArchiver(options, signalHandlers, services);
82+
({ config } = await startArchiver(options, signalHandlers, services));
8083
} else if (options.p2pBootstrap) {
8184
const { startP2PBootstrap } = await import('./cmds/start_p2p_bootstrap.js');
82-
await startP2PBootstrap(options, signalHandlers, services, userLog);
85+
({ config } = await startP2PBootstrap(options, signalHandlers, services, userLog));
8386
} else if (options.proverAgent) {
8487
const { startProverAgent } = await import('./cmds/start_prover_agent.js');
8588
await startProverAgent(options, signalHandlers, services, userLog);
@@ -102,14 +105,14 @@ export async function aztecStart(options: any, userLog: LogFn, debugLogger: Logg
102105
}
103106

104107
installSignalHandlers(debugLogger.info, signalHandlers);
105-
108+
const versions = getVersions(config);
106109
if (Object.entries(services).length > 0) {
107110
const rpcServer = createNamespacedSafeJsonRpcServer(services, {
108111
http200OnError: false,
109112
log: debugLogger,
110-
middlewares: [getOtelJsonRpcPropagationMiddleware()],
113+
middlewares: [getOtelJsonRpcPropagationMiddleware(), getVersioningMiddleware(versions)],
111114
});
112115
const { port } = await startHttpRpcServer(rpcServer, { port: options.port });
113-
debugLogger.info(`Aztec Server listening on port ${port}`);
116+
debugLogger.info(`Aztec Server listening on port ${port}`, versions);
114117
}
115118
}

yarn-project/aztec/src/cli/cmds/start_archiver.ts

+5-2
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,14 @@ import { getConfigEnvVars as getTelemetryClientConfig, initTelemetryClient } fro
1616
import { extractRelevantOptions } from '../util.js';
1717
import { validateL1Config } from '../validation.js';
1818

19+
export type { ArchiverConfig, DataStoreConfig };
20+
1921
/** Starts a standalone archiver. */
2022
export async function startArchiver(
2123
options: any,
2224
signalHandlers: (() => Promise<void>)[],
2325
services: NamespacedApiHandlers,
24-
) {
26+
): Promise<{ config: ArchiverConfig & DataStoreConfig }> {
2527
const archiverConfig = extractRelevantOptions<ArchiverConfig & DataStoreConfig>(
2628
options,
2729
{
@@ -43,5 +45,6 @@ export async function startArchiver(
4345
const archiver = await Archiver.createAndSync(archiverConfig, archiverStore, { telemetry, blobSinkClient }, true);
4446
services.archiver = [archiver, ArchiverApiSchema];
4547
signalHandlers.push(archiver.stop);
46-
return services;
48+
49+
return { config: archiverConfig };
4750
}

yarn-project/aztec/src/cli/cmds/start_bot.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export async function startBot(
2424
let pxe: PXE | undefined;
2525
if (options.pxe) {
2626
const { addPXE } = await import('./start_pxe.js');
27-
pxe = await addPXE(options, signalHandlers, services, userLog);
27+
({ pxe } = await addPXE(options, signalHandlers, services, userLog));
2828
}
2929

3030
const telemetry = initTelemetryClient(getTelemetryClientConfig());

yarn-project/aztec/src/cli/cmds/start_node.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -112,12 +112,14 @@ export async function startNode(
112112
let pxe: PXE | undefined;
113113
if (options.pxe) {
114114
const { addPXE } = await import('./start_pxe.js');
115-
pxe = await addPXE(options, signalHandlers, services, userLog, { node });
115+
({ pxe } = await addPXE(options, signalHandlers, services, userLog, { node }));
116116
}
117117

118118
// Add a txs bot if requested
119119
if (options.bot) {
120120
const { addBot } = await import('./start_bot.js');
121121
await addBot(options, signalHandlers, services, { pxe, node, telemetry });
122122
}
123+
124+
return { config: nodeConfig };
123125
}

yarn-project/aztec/src/cli/cmds/start_p2p_bootstrap.ts

+1
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,5 @@ export async function startP2PBootstrap(
2222
signalHandlers.push(() => node.stop());
2323
services.bootstrap = [node, P2PBootstrapApiSchema];
2424
userLog(`P2P bootstrap node started on ${config.udpListenAddress}`);
25+
return { config };
2526
}

yarn-project/aztec/src/cli/cmds/start_prover_agent.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { getProverNodeAgentConfigFromEnv } from '@aztec/prover-node';
1313
import { initTelemetryClient, telemetryClientConfigMappings } from '@aztec/telemetry-client';
1414

1515
import { extractRelevantOptions } from '../util.js';
16+
import { getVersions } from '../versioning.js';
1617

1718
export async function startProverAgent(
1819
options: any,
@@ -38,7 +39,7 @@ export async function startProverAgent(
3839
process.exit(1);
3940
}
4041

41-
const broker = createProvingJobBrokerClient(config.proverBrokerUrl);
42+
const broker = createProvingJobBrokerClient(config.proverBrokerUrl, getVersions());
4243

4344
const telemetry = initTelemetryClient(extractRelevantOptions(options, telemetryClientConfigMappings, 'tel'));
4445
const prover = await buildServerCircuitProver(config, telemetry);

yarn-project/aztec/src/cli/cmds/start_prover_broker.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ export async function startProverBroker(
1717
signalHandlers: (() => Promise<void>)[],
1818
services: NamespacedApiHandlers,
1919
userLog: LogFn,
20-
): Promise<ProvingJobBroker> {
20+
): Promise<{ broker: ProvingJobBroker; config: ProverBrokerConfig }> {
2121
if (options.node || options.sequencer || options.pxe || options.p2pBootstrap || options.txe) {
2222
userLog(`Starting a prover broker with --node, --sequencer, --pxe, --p2p-bootstrap, or --txe is not supported.`);
2323
process.exit(1);
@@ -33,5 +33,5 @@ export async function startProverBroker(
3333
services.proverBroker = [broker, ProvingJobBrokerSchema];
3434
signalHandlers.push(() => broker.stop());
3535

36-
return broker;
36+
return { broker, config };
3737
}

0 commit comments

Comments
 (0)