Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion yarn-project/aztec-node/src/aztec-node/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,12 @@ import {
getTelemetryClient,
trackSpan,
} from '@aztec/telemetry-client';
import { NodeKeystoreAdapter, ValidatorClient, createValidatorClient } from '@aztec/validator-client';
import {
NodeKeystoreAdapter,
ValidatorClient,
createBlockProposalHandler,
createValidatorClient,
} from '@aztec/validator-client';
import { createWorldStateSynchronizer } from '@aztec/world-state';

import { createPublicClient, fallback, http } from 'viem';
Expand Down Expand Up @@ -336,6 +341,21 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
}
}

// If there's no validator client but alwaysReexecuteBlockProposals is enabled,
// create a BlockProposalHandler to reexecute block proposals for monitoring
if (!validatorClient && config.alwaysReexecuteBlockProposals) {
log.info('Setting up block proposal reexecution for monitoring');
createBlockProposalHandler(config, {
blockBuilder,
epochCache,
blockSource: archiver,
l1ToL2MessageSource: archiver,
p2pClient,
dateProvider,
telemetry,
}).registerForReexecution(p2pClient);
}

// Start world state and wait for it to sync to the archiver.
await worldStateSynchronizer.start();

Expand Down
4 changes: 2 additions & 2 deletions yarn-project/cli/src/config/chain_l2_config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ const DefaultSlashConfig = {
slashProposeInvalidAttestationsPenalty: DefaultL1ContractsConfig.slashAmountLarge,
slashAttestDescendantOfInvalidPenalty: DefaultL1ContractsConfig.slashAmountLarge,
slashUnknownPenalty: DefaultL1ContractsConfig.slashAmountSmall,
slashBroadcastedInvalidBlockPenalty: DefaultL1ContractsConfig.slashAmountMedium,
slashBroadcastedInvalidBlockPenalty: 0n, // DefaultL1ContractsConfig.slashAmountSmall // Disabled until further testing
slashMaxPayloadSize: 50,
slashGracePeriodL2Slots: 32 * 2, // Two epochs from genesis
slashOffenseExpirationRounds: 8,
Expand Down Expand Up @@ -142,7 +142,7 @@ export const stagingIgnitionL2ChainConfig: L2ChainConfig = {
slashProposeInvalidAttestationsPenalty: 50_000n * 10n ** 18n,
slashAttestDescendantOfInvalidPenalty: 50_000n * 10n ** 18n,
slashUnknownPenalty: 2_000n * 10n ** 18n,
slashBroadcastedInvalidBlockPenalty: 10_000n * 10n ** 18n,
slashBroadcastedInvalidBlockPenalty: 0n, // 10_000n * 10n ** 18n, Disabled for now until further testing
slashMaxPayloadSize: 50,
slashGracePeriodL2Slots: 32 * 4, // One round from genesis
slashOffenseExpirationRounds: 8,
Expand Down
28 changes: 25 additions & 3 deletions yarn-project/end-to-end/src/e2e_p2p/gossip_network.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { Archiver } from '@aztec/archiver';
import type { AztecNodeService } from '@aztec/aztec-node';
import type { AztecNodeConfig, AztecNodeService } from '@aztec/aztec-node';
import { SentTx, retryUntil, sleep } from '@aztec/aztec.js';
import type { ProverNode } from '@aztec/prover-node';
import type { SequencerClient } from '@aztec/sequencer-client';
Expand All @@ -12,7 +12,12 @@ import os from 'os';
import path from 'path';

import { shouldCollectMetrics } from '../fixtures/fixtures.js';
import { ATTESTER_PRIVATE_KEYS_START_INDEX, createNodes, createProverNode } from '../fixtures/setup_p2p_test.js';
import {
ATTESTER_PRIVATE_KEYS_START_INDEX,
createNodes,
createNonValidatorNode,
createProverNode,
} from '../fixtures/setup_p2p_test.js';
import { AlertChecker, type AlertConfig } from '../quality_of_service/alert_checker.js';
import { P2PNetworkTest, SHORTENED_BLOCK_TIME_CONFIG_NO_PRUNES, WAIT_FOR_TX_TIMEOUT } from './p2p_network.js';
import { submitTransactions } from './shared.js';
Expand Down Expand Up @@ -42,6 +47,7 @@ describe('e2e_p2p_network', () => {
let t: P2PNetworkTest;
let nodes: AztecNodeService[];
let proverNode: ProverNode;
let monitoringNode: AztecNodeService;

beforeEach(async () => {
t = await P2PNetworkTest.create({
Expand All @@ -66,6 +72,9 @@ describe('e2e_p2p_network', () => {

afterEach(async () => {
await tryStop(proverNode);
fs.rmSync(`${DATA_DIR}-prover`, { recursive: true, force: true, maxRetries: 3 });
await tryStop(monitoringNode);
fs.rmSync(`${DATA_DIR}-monitor`, { recursive: true, force: true, maxRetries: 3 });
await t.stopNodes(nodes);
await t.teardown();
for (let i = 0; i < NUM_VALIDATORS; i++) {
Expand Down Expand Up @@ -93,7 +102,7 @@ describe('e2e_p2p_network', () => {
// should be set so that the only way for rollups to be built
// is if the txs are successfully gossiped around the nodes.
const txsSentViaDifferentNodes: SentTx[][] = [];
t.logger.info('Creating nodes');
t.logger.info('Creating validator nodes');
nodes = await createNodes(
t.ctx.aztecNodeConfig,
t.ctx.dateProvider,
Expand All @@ -107,6 +116,7 @@ describe('e2e_p2p_network', () => {
);

// create a prover node that uses p2p only (not rpc) to gather txs to test prover tx collection
t.logger.warn(`Creating prover node`);
proverNode = await createProverNode(
t.ctx.aztecNodeConfig,
BOOT_NODE_UDP_PORT + NUM_VALIDATORS + 1,
Expand All @@ -119,6 +129,18 @@ describe('e2e_p2p_network', () => {
);
await proverNode.start();

t.logger.warn(`Creating non validator node`);
const monitoringNodeConfig: AztecNodeConfig = { ...t.ctx.aztecNodeConfig, alwaysReexecuteBlockProposals: true };
monitoringNode = await createNonValidatorNode(
monitoringNodeConfig,
t.ctx.dateProvider,
BOOT_NODE_UDP_PORT + NUM_VALIDATORS + 2,
t.bootstrapNodeEnr,
t.prefilledPublicData,
`${DATA_DIR}-monitor`,
shouldCollectMetrics(),
);

// wait a bit for peers to discover each other
await sleep(8000);

Expand Down
69 changes: 53 additions & 16 deletions yarn-project/end-to-end/src/fixtures/setup_p2p_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export async function createNodes(
return nodes;
}

// creates a P2P enabled instance of Aztec Node Service
/** Creates a P2P enabled instance of Aztec Node Service with a validator */
export async function createNode(
config: AztecNodeConfig & { dontStartSequencer?: boolean },
dateProvider: DateProvider,
Expand All @@ -102,6 +102,31 @@ export async function createNode(
return loggerIdStorage ? await loggerIdStorage.run(tcpPort.toString(), createNode) : createNode();
}

/** Creates a P2P enabled instance of Aztec Node Service without a validator */
export async function createNonValidatorNode(
baseConfig: AztecNodeConfig,
dateProvider: DateProvider,
tcpPort: number,
bootstrapNode: string | undefined,
prefilledPublicData?: PublicDataTreeLeaf[],
dataDirectory?: string,
metricsPort?: number,
loggerIdStorage?: AsyncLocalStorage<string>,
) {
const createNode = async () => {
const p2pConfig = await createP2PConfig(baseConfig, bootstrapNode, tcpPort, dataDirectory);
const config: AztecNodeConfig = {
...p2pConfig,
disableValidator: true,
validatorPrivateKeys: undefined,
publisherPrivateKeys: [],
};
const telemetry = getEndToEndTestTelemetryClient(metricsPort);
return await AztecNodeService.createAndSync(config, { telemetry, dateProvider }, { prefilledPublicData });
};
return loggerIdStorage ? await loggerIdStorage.run(tcpPort.toString(), createNode) : createNode();
}

export async function createProverNode(
config: AztecNodeConfig,
tcpPort: number,
Expand All @@ -117,14 +142,13 @@ export async function createProverNode(
const proverNodePrivateKey = getPrivateKeyFromIndex(ATTESTER_PRIVATE_KEYS_START_INDEX + addressIndex)!;
const telemetry = getEndToEndTestTelemetryClient(metricsPort);

const proverConfig: Partial<ProverNodeConfig> = {
p2pIp: `127.0.0.1`,
p2pPort: tcpPort ?? (await getPort()),
p2pEnabled: true,
peerCheckIntervalMS: TEST_PEER_CHECK_INTERVAL_MS,
blockCheckIntervalMS: 1000,
bootstrapNodes: bootstrapNode ? [bootstrapNode] : [],
};
const proverConfig: Partial<ProverNodeConfig> = await createP2PConfig(
config,
bootstrapNode,
tcpPort,
dataDirectory,
);

const aztecNodeRpcTxProvider = undefined;
return await createAndSyncProverNode(
bufferToHex(proverNodePrivateKey),
Expand All @@ -138,20 +162,14 @@ export async function createProverNode(
return loggerIdStorage ? await loggerIdStorage.run(tcpPort.toString(), createProverNode) : createProverNode();
}

export async function createValidatorConfig(
export async function createP2PConfig(
config: AztecNodeConfig,
bootstrapNodeEnr?: string,
port?: number,
addressIndex: number = 1,
dataDirectory?: string,
) {
port = port ?? (await getPort());

const attesterPrivateKey = bufferToHex(getPrivateKeyFromIndex(ATTESTER_PRIVATE_KEYS_START_INDEX + addressIndex)!);

config.validatorPrivateKeys = new SecretValue([attesterPrivateKey]);
config.publisherPrivateKeys = [new SecretValue(attesterPrivateKey)];

const nodeConfig: AztecNodeConfig = {
...config,
p2pIp: `127.0.0.1`,
Expand All @@ -165,3 +183,22 @@ export async function createValidatorConfig(

return nodeConfig;
}

export async function createValidatorConfig(
config: AztecNodeConfig,
bootstrapNodeEnr?: string,
port?: number,
addressIndex: number = 1,
dataDirectory?: string,
) {
const attesterPrivateKey = bufferToHex(getPrivateKeyFromIndex(ATTESTER_PRIVATE_KEYS_START_INDEX + addressIndex)!);
const p2pConfig = await createP2PConfig(config, bootstrapNodeEnr, port, dataDirectory);
const nodeConfig: AztecNodeConfig = {
...config,
...p2pConfig,
validatorPrivateKeys: new SecretValue([attesterPrivateKey]),
publisherPrivateKeys: [new SecretValue(attesterPrivateKey)],
};

return nodeConfig;
}
1 change: 1 addition & 0 deletions yarn-project/foundation/src/config/env_var.ts
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,7 @@ export type EnvVar =
| 'K8S_POD_UID'
| 'K8S_NAMESPACE_NAME'
| 'VALIDATOR_REEXECUTE_DEADLINE_MS'
| 'ALWAYS_REEXECUTE_BLOCK_PROPOSALS'
| 'AUTO_UPDATE'
| 'AUTO_UPDATE_URL'
| 'WEB3_SIGNER_URL';
2 changes: 1 addition & 1 deletion yarn-project/slasher/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ export const slasherConfigMappings: ConfigMappingsType<SlasherConfig> = {
},
slashBroadcastedInvalidBlockPenalty: {
env: 'SLASH_INVALID_BLOCK_PENALTY',
description: 'Penalty amount for slashing a validator for an invalid block.',
description: 'Penalty amount for slashing a validator for an invalid block proposed via p2p.',
...bigintConfigHelper(DefaultSlasherConfig.slashBroadcastedInvalidBlockPenalty),
},
slashInactivityTargetPercentage: {
Expand Down
6 changes: 5 additions & 1 deletion yarn-project/stdlib/src/interfaces/validator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,14 @@ export interface ValidatorClientConfig {
/** Interval between polling for new attestations from peers */
attestationPollingIntervalMs: number;

/** Re-execute transactions before attesting */
/** Whether to re-execute transactions in a block proposal before attesting */
validatorReexecute: boolean;

/** Will re-execute until this many milliseconds are left in the slot */
validatorReexecuteDeadlineMs: number;

/** Whether to always reexecute block proposals, even for non-validator nodes or when out of the currnet committee */
alwaysReexecuteBlockProposals?: boolean;
}

export type ValidatorClientFullConfig = ValidatorClientConfig &
Expand All @@ -50,6 +53,7 @@ export const ValidatorClientConfigSchema = z.object({
attestationPollingIntervalMs: z.number().min(0),
validatorReexecute: z.boolean(),
validatorReexecuteDeadlineMs: z.number().min(0),
alwaysReexecuteBlockProposals: z.boolean().optional(),
}) satisfies ZodFor<Omit<ValidatorClientConfig, 'validatorPrivateKeys'>>;

export interface Validator {
Expand Down
4 changes: 3 additions & 1 deletion yarn-project/telemetry-client/src/attributes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,14 @@ export const P2P_GOODBYE_REASON = 'aztec.p2p.goodbye.reason';
export const PROVING_JOB_TYPE = 'aztec.proving.job_type';
/** The proving job id */
export const PROVING_JOB_ID = 'aztec.proving.job_id';

/** Merkle tree name */
export const MERKLE_TREE_NAME = 'aztec.merkle_tree.name';
/** The prover-id in a root rollup proof. */
export const ROLLUP_PROVER_ID = 'aztec.rollup.prover_id';
/** Whether the proof submission was timed out (delayed more than 20 min) */
export const PROOF_TIMED_OUT = 'aztec.proof.timed_out';
/** Status of the validator (eg proposer, in-committee, none) */
export const VALIDATOR_STATUS = 'aztec.validator_status';

export const P2P_ID = 'aztec.p2p.id';
export const P2P_REQ_RESP_PROTOCOL = 'aztec.p2p.req_resp.protocol';
Expand Down
Loading
Loading