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
131 changes: 71 additions & 60 deletions yarn-project/aztec-node/src/aztec-node/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ import {
import type { DebugLogStore, LogFilter, SiloedTag, Tag, TxScopedL2Log } from '@aztec/stdlib/logs';
import { InMemoryDebugLogStore, NullDebugLogStore } from '@aztec/stdlib/logs';
import { InboxLeaf, type L1ToL2MessageSource } from '@aztec/stdlib/messaging';
import { P2PClientType } from '@aztec/stdlib/p2p';
import type { Offense, SlashPayloadRound } from '@aztec/stdlib/slashing';
import type { NullifierLeafPreimage, PublicDataTreeLeaf, PublicDataTreeLeafPreimage } from '@aztec/stdlib/trees';
import { MerkleTreeId, NullifierMembershipWitness, PublicDataWitness } from '@aztec/stdlib/trees';
Expand Down Expand Up @@ -194,7 +193,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
logger?: Logger;
publisher?: SequencerPublisher;
dateProvider?: DateProvider;
p2pClientDeps?: P2PClientDeps<P2PClientType.Full>;
p2pClientDeps?: P2PClientDeps;
proverNodeDeps?: Partial<ProverNodeDeps>;
} = {},
options: {
Expand Down Expand Up @@ -325,9 +324,13 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {

const proofVerifier = new QueuedIVCVerifier(config, circuitVerifier);

const proverOnly = config.enableProverNode && config.disableValidator;
if (proverOnly) {
log.info('Starting in prover-only mode: skipping validator, sequencer, sentinel, and slasher subsystems');
}

// create the tx pool and the p2p client, which will need the l2 block source
const p2pClient = await createP2PClient(
P2PClientType.Full,
config,
archiver,
proofVerifier,
Expand All @@ -342,7 +345,10 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
// We should really not be modifying the config object
config.txPublicSetupAllowList = config.txPublicSetupAllowList ?? (await getDefaultAllowedSetupFunctions());

// Create FullNodeCheckpointsBuilder for validator and non-validator block proposal handling
// We'll accumulate sentinel watchers here
const watchers: Watcher[] = [];

// Create FullNodeCheckpointsBuilder for block proposal handling and tx validation
const validatorCheckpointsBuilder = new FullNodeCheckpointsBuilder(
{ ...config, l1GenesisTime, slotDuration: Number(slotDuration) },
worldStateSynchronizer,
Expand All @@ -351,47 +357,48 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
telemetry,
);

// We'll accumulate sentinel watchers here
const watchers: Watcher[] = [];

// Create validator client if required
const validatorClient = await createValidatorClient(config, {
checkpointsBuilder: validatorCheckpointsBuilder,
worldState: worldStateSynchronizer,
p2pClient,
telemetry,
dateProvider,
epochCache,
blockSource: archiver,
l1ToL2MessageSource: archiver,
keyStoreManager,
blobClient,
});

// If we have a validator client, register it as a source of offenses for the slasher,
// and have it register callbacks on the p2p client *before* we start it, otherwise messages
// like attestations or auths will fail.
if (validatorClient) {
watchers.push(validatorClient);
if (!options.dontStartSequencer) {
await validatorClient.registerHandlers();
}
}
let validatorClient: ValidatorClient | undefined;

// 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, {
if (!proverOnly) {
// Create validator client if required
validatorClient = await createValidatorClient(config, {
checkpointsBuilder: validatorCheckpointsBuilder,
worldState: worldStateSynchronizer,
p2pClient,
telemetry,
dateProvider,
epochCache,
blockSource: archiver,
l1ToL2MessageSource: archiver,
p2pClient,
dateProvider,
telemetry,
}).registerForReexecution(p2pClient);
keyStoreManager,
blobClient,
});

// If we have a validator client, register it as a source of offenses for the slasher,
// and have it register callbacks on the p2p client *before* we start it, otherwise messages
// like attestations or auths will fail.
if (validatorClient) {
watchers.push(validatorClient);
if (!options.dontStartSequencer) {
await validatorClient.registerHandlers();
}
}

// 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, {
checkpointsBuilder: validatorCheckpointsBuilder,
worldState: worldStateSynchronizer,
epochCache,
blockSource: archiver,
l1ToL2MessageSource: archiver,
p2pClient,
dateProvider,
telemetry,
}).registerForReexecution(p2pClient);
}
}

// Start world state and wait for it to sync to the archiver.
Expand All @@ -400,29 +407,33 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
// Start p2p. Note that it depends on world state to be running.
await p2pClient.start();

const validatorsSentinel = await createSentinel(epochCache, archiver, p2pClient, config);
if (validatorsSentinel && config.slashInactivityPenalty > 0n) {
watchers.push(validatorsSentinel);
}

let validatorsSentinel: Awaited<ReturnType<typeof createSentinel>> | undefined;
let epochPruneWatcher: EpochPruneWatcher | undefined;
if (config.slashPrunePenalty > 0n || config.slashDataWithholdingPenalty > 0n) {
epochPruneWatcher = new EpochPruneWatcher(
archiver,
archiver,
epochCache,
p2pClient.getTxProvider(),
validatorCheckpointsBuilder,
config,
);
watchers.push(epochPruneWatcher);
}

// We assume we want to slash for invalid attestations unless all max penalties are set to 0
let attestationsBlockWatcher: AttestationsBlockWatcher | undefined;
if (config.slashProposeInvalidAttestationsPenalty > 0n || config.slashAttestDescendantOfInvalidPenalty > 0n) {
attestationsBlockWatcher = new AttestationsBlockWatcher(archiver, epochCache, config);
watchers.push(attestationsBlockWatcher);

if (!proverOnly) {
validatorsSentinel = await createSentinel(epochCache, archiver, p2pClient, config);
if (validatorsSentinel && config.slashInactivityPenalty > 0n) {
watchers.push(validatorsSentinel);
}

if (config.slashPrunePenalty > 0n || config.slashDataWithholdingPenalty > 0n) {
epochPruneWatcher = new EpochPruneWatcher(
archiver,
archiver,
epochCache,
p2pClient.getTxProvider(),
validatorCheckpointsBuilder,
config,
);
watchers.push(epochPruneWatcher);
}

// We assume we want to slash for invalid attestations unless all max penalties are set to 0
if (config.slashProposeInvalidAttestationsPenalty > 0n || config.slashAttestDescendantOfInvalidPenalty > 0n) {
attestationsBlockWatcher = new AttestationsBlockWatcher(archiver, epochCache, config);
watchers.push(attestationsBlockWatcher);
}
}

// Start p2p-related services once the archiver has completed sync
Expand Down
7 changes: 3 additions & 4 deletions yarn-project/end-to-end/src/fixtures/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ import type { SequencerClient } from '@aztec/sequencer-client';
import { type ContractInstanceWithAddress, getContractInstanceFromInstantiationParams } from '@aztec/stdlib/contract';
import type { AztecNodeAdmin } from '@aztec/stdlib/interfaces/client';
import { tryStop } from '@aztec/stdlib/interfaces/server';
import type { P2PClientType } from '@aztec/stdlib/p2p';
import type { PublicDataTreeLeaf } from '@aztec/stdlib/trees';
import {
type TelemetryClient,
Expand Down Expand Up @@ -456,7 +455,7 @@ export async function setup(
}

let mockGossipSubNetwork: MockGossipSubNetwork | undefined;
let p2pClientDeps: P2PClientDeps<P2PClientType.Full> | undefined = undefined;
let p2pClientDeps: P2PClientDeps | undefined = undefined;

if (opts.mockGossipSubNetwork) {
mockGossipSubNetwork = new MockGossipSubNetwork();
Expand Down Expand Up @@ -503,7 +502,7 @@ export async function setup(
const proverNodePrivateKeyHex: Hex = `0x${proverNodePrivateKey!.toString('hex')}`;
const proverNodeDataDirectory = path.join(directoryToCleanup, randomBytes(8).toString('hex'));

const p2pClientDeps: Partial<P2PClientDeps<P2PClientType.Full>> = {
const p2pClientDeps: Partial<P2PClientDeps> = {
p2pServiceFactory: mockGossipSubNetwork && getMockPubSubP2PServiceFactory(mockGossipSubNetwork!),
rpcTxProviders: [aztecNodeService],
};
Expand Down Expand Up @@ -719,7 +718,7 @@ export function createAndSyncProverNode(
deps: {
telemetry?: TelemetryClient;
dateProvider: DateProvider;
p2pClientDeps?: P2PClientDeps<P2PClientType.Full>;
p2pClientDeps?: P2PClientDeps;
},
options: { prefilledPublicData: PublicDataTreeLeaf[]; dontStart?: boolean },
): Promise<{ proverNode: AztecNodeService }> {
Expand Down
21 changes: 8 additions & 13 deletions yarn-project/p2p/src/client/factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import type { L2BlockSource } from '@aztec/stdlib/block';
import type { ChainConfig } from '@aztec/stdlib/config';
import type { ContractDataSource } from '@aztec/stdlib/contract';
import type { AztecNode, ClientProtocolCircuitVerifier, WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
import { P2PClientType } from '@aztec/stdlib/p2p';
import { type TelemetryClient, getTelemetryClient } from '@aztec/telemetry-client';

import { P2PClient } from '../client/p2p_client.js';
Expand All @@ -27,23 +26,22 @@ import { NodeRpcTxSource, type TxSource, createNodeRpcTxSources } from '../servi
import { TxFileStore } from '../services/tx_file_store/tx_file_store.js';
import { configureP2PClientAddresses, createLibP2PPeerIdFromPrivateKey, getPeerIdPrivateKey } from '../util.js';

export type P2PClientDeps<T extends P2PClientType> = {
export type P2PClientDeps = {
txPool?: TxPoolV2;
store?: AztecAsyncKVStore;
attestationPool?: AttestationPoolApi;
logger?: Logger;
txCollectionNodeSources?: TxSource[];
rpcTxProviders?: AztecNode[];
p2pServiceFactory?: (...args: Parameters<(typeof LibP2PService)['new']>) => Promise<LibP2PService<T>>;
p2pServiceFactory?: (...args: Parameters<(typeof LibP2PService)['new']>) => Promise<LibP2PService>;
};

export const P2P_STORE_NAME = 'p2p';
export const P2P_ARCHIVE_STORE_NAME = 'p2p-archive';
export const P2P_PEER_STORE_NAME = 'p2p-peers';
export const P2P_ATTESTATION_STORE_NAME = 'p2p-attestation';

export async function createP2PClient<T extends P2PClientType>(
clientType: T,
export async function createP2PClient(
inputConfig: P2PConfig & DataStoreConfig & ChainConfig,
archiver: L2BlockSource & ContractDataSource,
proofVerifier: ClientProtocolCircuitVerifier,
Expand All @@ -52,7 +50,7 @@ export async function createP2PClient<T extends P2PClientType>(
packageVersion: string,
dateProvider: DateProvider = new DateProvider(),
telemetry: TelemetryClient = getTelemetryClient(),
deps: P2PClientDeps<T> = {},
deps: P2PClientDeps = {},
) {
const config = await configureP2PClientAddresses({
...inputConfig,
Expand Down Expand Up @@ -111,9 +109,8 @@ export async function createP2PClient<T extends P2PClientType>(
attestationPool: deps.attestationPool ?? new AttestationPool(attestationStore, telemetry),
};

const p2pService = await createP2PService<T>(
const p2pService = await createP2PService(
config,
clientType,
archiver,
proofVerifier,
worldStateSynchronizer,
Expand Down Expand Up @@ -171,7 +168,6 @@ export async function createP2PClient<T extends P2PClientType>(
);

return new P2PClient(
clientType,
store,
archiver,
mempools,
Expand All @@ -185,17 +181,16 @@ export async function createP2PClient<T extends P2PClientType>(
);
}

async function createP2PService<T extends P2PClientType>(
async function createP2PService(
config: P2PConfig & DataStoreConfig,
clientType: T,
archiver: L2BlockSource & ContractDataSource,
proofVerifier: ClientProtocolCircuitVerifier,
worldStateSynchronizer: WorldStateSynchronizer,
epochCache: EpochCacheInterface,
store: AztecAsyncKVStore,
peerStore: AztecLMDBStoreV2,
mempools: MemPools,
p2pServiceFactory: P2PClientDeps<T>['p2pServiceFactory'],
p2pServiceFactory: P2PClientDeps['p2pServiceFactory'],
packageVersion: string,
logger: Logger,
telemetry: TelemetryClient,
Expand All @@ -211,7 +206,7 @@ async function createP2PService<T extends P2PClientType>(
const peerIdPrivateKey = await getPeerIdPrivateKey(config, store, logger);
const peerId = await createLibP2PPeerIdFromPrivateKey(peerIdPrivateKey.getValue());

const p2pService = await (p2pServiceFactory ?? LibP2PService.new<T>)(clientType, config, peerId, {
const p2pService = await (p2pServiceFactory ?? LibP2PService.new)(config, peerId, {
packageVersion,
mempools,
l2BlockSource: archiver,
Expand Down
12 changes: 3 additions & 9 deletions yarn-project/p2p/src/client/interface.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
import type { SlotNumber } from '@aztec/foundation/branded-types';
import type { EthAddress, L2BlockId } from '@aztec/stdlib/block';
import type { ITxProvider, P2PApiFull } from '@aztec/stdlib/interfaces/server';
import type {
BlockProposal,
CheckpointAttestation,
CheckpointProposal,
P2PClientType,
TopicType,
} from '@aztec/stdlib/p2p';
import type { ITxProvider, P2PClient } from '@aztec/stdlib/interfaces/server';
import type { BlockProposal, CheckpointAttestation, CheckpointProposal, TopicType } from '@aztec/stdlib/p2p';
import type { BlockHeader, Tx, TxHash } from '@aztec/stdlib/tx';

import type { PeerId } from '@libp2p/interface';
Expand Down Expand Up @@ -54,7 +48,7 @@ export interface P2PSyncState {
/**
* Interface of a P2P client.
**/
export type P2P<T extends P2PClientType = P2PClientType.Full> = P2PApiFull<T> & {
export type P2P = P2PClient & {
/**
* Broadcasts a block proposal to other peers.
*
Expand Down
13 changes: 1 addition & 12 deletions yarn-project/p2p/src/client/p2p_client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import type { AztecAsyncKVStore } from '@aztec/kv-store';
import { openTmpStore } from '@aztec/kv-store/lmdb-v2';
import { L2Block } from '@aztec/stdlib/block';
import { EmptyL1RollupConstants, type L1RollupConstants } from '@aztec/stdlib/epoch-helpers';
import { P2PClientType } from '@aztec/stdlib/p2p';
import { mockTx } from '@aztec/stdlib/testing';
import { TxHash } from '@aztec/stdlib/tx';

Expand Down Expand Up @@ -62,17 +61,7 @@ describe('P2P Client', () => {
});

const createClient = (config: Partial<P2PConfig> = {}) =>
new P2PClient(
P2PClientType.Full,
kvStore,
blockSource,
mempools,
p2pService,
txCollection,
undefined,
epochCache,
config,
);
new P2PClient(kvStore, blockSource, mempools, p2pService, txCollection, undefined, epochCache, config);

const advanceToProvenBlock = async (blockNumber: BlockNumber) => {
blockSource.setProvenBlockNumber(blockNumber);
Expand Down
14 changes: 2 additions & 12 deletions yarn-project/p2p/src/client/p2p_client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,7 @@ import {
import type { ContractDataSource } from '@aztec/stdlib/contract';
import { getTimestampForSlot } from '@aztec/stdlib/epoch-helpers';
import { type PeerInfo, tryStop } from '@aztec/stdlib/interfaces/server';
import {
type BlockProposal,
CheckpointAttestation,
type CheckpointProposal,
type P2PClientType,
type TopicType,
} from '@aztec/stdlib/p2p';
import { type BlockProposal, CheckpointAttestation, type CheckpointProposal, type TopicType } from '@aztec/stdlib/p2p';
import type { BlockHeader, Tx, TxHash } from '@aztec/stdlib/tx';
import { Attributes, type TelemetryClient, WithTracer, getTelemetryClient, trackSpan } from '@aztec/telemetry-client';

Expand Down Expand Up @@ -59,10 +53,7 @@ import { type P2P, P2PClientState, type P2PSyncState } from './interface.js';
/**
* The P2P client implementation.
*/
export class P2PClient<T extends P2PClientType = P2PClientType.Full>
extends WithTracer
implements P2P, P2P<P2PClientType.Prover>
{
export class P2PClient extends WithTracer implements P2P {
/** The JS promise that will be running to keep the client's data in sync. Can be interrupted if the client is stopped. */
private runningPromise!: Promise<void>;

Expand Down Expand Up @@ -94,7 +85,6 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
private slotMonitor: RunningPromise | undefined;

constructor(
_clientType: T,
private store: AztecAsyncKVStore,
private l2BlockSource: L2BlockSource & ContractDataSource,
mempools: MemPools,
Expand Down
Loading
Loading