Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(prover): prover node should not gossip attestations #10672

Merged
merged 8 commits into from
Dec 13, 2024
Merged
Show file tree
Hide file tree
Changes from 2 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
5 changes: 3 additions & 2 deletions yarn-project/aztec-node/src/aztec-node/server.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
MerkleTreeId,
type MerkleTreeReadOperations,
type NullifierWithBlockSource,
type P2PClientType,
type WorldStateSynchronizer,
mockTxForRollup,
} from '@aztec/circuit-types';
Expand All @@ -21,7 +22,7 @@ import { type AztecNodeConfig, getConfigEnvVars } from './config.js';
import { AztecNodeService } from './server.js';

describe('aztec node', () => {
let p2p: MockProxy<P2P>;
let p2p: MockProxy<P2P<P2PClientType.Full>>;
let globalVariablesBuilder: MockProxy<GlobalVariableBuilder>;
let merkleTreeOps: MockProxy<MerkleTreeReadOperations>;

Expand All @@ -34,7 +35,7 @@ describe('aztec node', () => {
beforeEach(() => {
lastBlockNumber = 0;

p2p = mock<P2P>();
p2p = mock<P2P<P2PClientType.Full>>();

globalVariablesBuilder = mock<GlobalVariableBuilder>();
merkleTreeOps = mock<MerkleTreeReadOperations>();
Expand Down
14 changes: 11 additions & 3 deletions yarn-project/aztec-node/src/aztec-node/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
MerkleTreeId,
NullifierMembershipWitness,
type NullifierWithBlockSource,
P2PClientType,
type ProcessedTx,
type ProverConfig,
PublicDataWitness,
Expand Down Expand Up @@ -92,7 +93,7 @@ export class AztecNodeService implements AztecNode {

constructor(
protected config: AztecNodeConfig,
protected readonly p2pClient: P2P,
protected readonly p2pClient: P2P<P2PClientType.Full>,
protected readonly blockSource: L2BlockSource & Partial<Service>,
protected readonly logsSource: L2LogsSource,
protected readonly contractDataSource: ContractDataSource,
Expand Down Expand Up @@ -162,7 +163,14 @@ export class AztecNodeService implements AztecNode {
}

// create the tx pool and the p2p client, which will need the l2 block source
const p2pClient = await createP2PClient(config, archiver, proofVerifier, worldStateSynchronizer, telemetry);
const p2pClient = await createP2PClient(
P2PClientType.Full,
config,
archiver,
proofVerifier,
worldStateSynchronizer,
telemetry,
);

// start both and wait for them to sync from the block source
await Promise.all([p2pClient.start(), worldStateSynchronizer.start()]);
Expand Down Expand Up @@ -214,7 +222,7 @@ export class AztecNodeService implements AztecNode {
return this.blockSource;
}

public getP2P(): P2P {
public getP2P(): P2P<P2PClientType.Full> {
return this.p2pClient;
}

Expand Down
7 changes: 4 additions & 3 deletions yarn-project/circuit-types/src/interfaces/p2p.test.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
import { type JsonRpcTestContext, createJsonRpcTestSetup } from '@aztec/foundation/json-rpc/test';

import { BlockAttestation } from '../p2p/block_attestation.js';
import { type P2PClientType } from '../p2p/client_type.js';
import { EpochProofQuote } from '../prover_coordination/epoch_proof_quote.js';
import { Tx } from '../tx/tx.js';
import { type P2PApi, P2PApiSchema, type PeerInfo } from './p2p.js';

describe('P2PApiSchema', () => {
let handler: MockP2P;
let context: JsonRpcTestContext<P2PApi>;
let context: JsonRpcTestContext<P2PApi<P2PClientType.Full>>;

const tested = new Set<string>();

beforeEach(async () => {
handler = new MockP2P();
context = await createJsonRpcTestSetup<P2PApi>(handler, P2PApiSchema);
context = await createJsonRpcTestSetup<P2PApi<P2PClientType.Full>>(handler, P2PApiSchema);
});

afterEach(() => {
Expand Down Expand Up @@ -65,7 +66,7 @@ const peers: PeerInfo[] = [
{ status: 'cached', id: 'id', addresses: ['address'], enr: 'enr', dialAttempts: 1 },
];

class MockP2P implements P2PApi {
class MockP2P implements P2PApi<P2PClientType.Full> {
getAttestationsForSlot(slot: bigint, proposalId?: string | undefined): Promise<BlockAttestation[]> {
expect(slot).toEqual(1n);
expect(proposalId).toEqual('proposalId');
Expand Down
29 changes: 18 additions & 11 deletions yarn-project/circuit-types/src/interfaces/p2p.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { type ApiSchemaFor, optional, schemas } from '@aztec/foundation/schemas'
import { z } from 'zod';

import { BlockAttestation } from '../p2p/block_attestation.js';
import { type P2PClientType } from '../p2p/client_type.js';
import { EpochProofQuote } from '../prover_coordination/epoch_proof_quote.js';
import { Tx } from '../tx/tx.js';

Expand All @@ -24,16 +25,7 @@ const PeerInfoSchema = z.discriminatedUnion('status', [
]);

/** Exposed API to the P2P module. */
export interface P2PApi {
/**
* Queries the Attestation pool for attestations for the given slot
*
* @param slot - the slot to query
* @param proposalId - the proposal id to query, or undefined to query all proposals for the slot
* @returns BlockAttestations
*/
getAttestationsForSlot(slot: bigint, proposalId?: string): Promise<BlockAttestation[]>;

export interface P2PApiWithoutAttestations {
/**
* Queries the EpochProofQuote pool for quotes for the given epoch
*
Expand All @@ -59,7 +51,22 @@ export interface P2PApi {
getPeers(includePending?: boolean): Promise<PeerInfo[]>;
}

export const P2PApiSchema: ApiSchemaFor<P2PApi> = {
export interface P2PClient extends P2PApiWithoutAttestations {
/**
* Queries the Attestation pool for attestations for the given slot
*
* @param slot - the slot to query
* @param proposalId - the proposal id to query, or undefined to query all proposals for the slot
* @returns BlockAttestations
*/
getAttestationsForSlot(slot: bigint, proposalId?: string): Promise<BlockAttestation[]>;
}

export type P2PApi<T extends P2PClientType> = T extends P2PClientType.Full
? P2PClient & P2PApiWithoutAttestations
: P2PApiWithoutAttestations;

export const P2PApiSchema: ApiSchemaFor<P2PApi<P2PClientType.Full>> = {
getAttestationsForSlot: z
.function()
.args(schemas.BigInt, optional(z.string()))
Expand Down
6 changes: 6 additions & 0 deletions yarn-project/circuit-types/src/p2p/client_type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export enum P2PClientType {
// Full p2p clients will subscribe to all gossip topics
Full,
// Prove p2p clients will only subscribe to transaction and proving topics
Prover,
}
1 change: 1 addition & 0 deletions yarn-project/circuit-types/src/p2p/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ export * from './gossipable.js';
export * from './interface.js';
export * from './signature_utils.js';
export * from './topic_type.js';
export * from './client_type.js';
9 changes: 9 additions & 0 deletions yarn-project/circuit-types/src/p2p/topic_type.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { P2PClientType } from './client_type.js';

/** Create Topic String
*
* The topic channel identifier
Expand All @@ -18,6 +20,13 @@ export enum TopicType {
epoch_proof_quote = 'epoch_proof_quote',
}

export function getTopicTypeForClientType(clientType: P2PClientType) {
if (clientType === P2PClientType.Full) {
return Object.values(TopicType);
}
return [TopicType.tx, TopicType.epoch_proof_quote];
}

/**
* Convert the topic string into a set of labels
*
Expand Down
14 changes: 14 additions & 0 deletions yarn-project/ivc-integration/defl.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/bin/bash

testname=$1
script_dir=$(dirname "$0")

for i in {1..100}
do
echo "Run #$i"
if ! taskset -c 0-1 yarn test $1 > $script_dir/deflaker.log 2>&1; then
echo "failed"
exit 1
fi
done
echo "success"
46 changes: 34 additions & 12 deletions yarn-project/p2p/src/client/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import type { ClientProtocolCircuitVerifier, L2BlockSource, WorldStateSynchronizer } from '@aztec/circuit-types';
import {
type ClientProtocolCircuitVerifier,
type L2BlockSource,
P2PClientType,
type WorldStateSynchronizer,
} from '@aztec/circuit-types';
import { createLogger } from '@aztec/foundation/log';
import { type AztecKVStore } from '@aztec/kv-store';
import { type DataStoreConfig } from '@aztec/kv-store/config';
Expand All @@ -21,27 +26,35 @@ import { configureP2PClientAddresses, createLibP2PPeerIdFromPrivateKey, getPeerI

export * from './p2p_client.js';

export const createP2PClient = async (
type P2PClientDeps<T extends P2PClientType> = {
txPool?: TxPool;
store?: AztecKVStore;
attestationPool?: T extends P2PClientType.Full ? AttestationPool : undefined;
epochProofQuotePool?: EpochProofQuotePool;
};

export const createP2PClient = async <T extends P2PClientType>(
clientType: T,
_config: P2PConfig & DataStoreConfig,
l2BlockSource: L2BlockSource,
proofVerifier: ClientProtocolCircuitVerifier,
worldStateSynchronizer: WorldStateSynchronizer,
telemetry: TelemetryClient = new NoopTelemetryClient(),
deps: {
txPool?: TxPool;
store?: AztecKVStore;
attestationPool?: AttestationPool;
epochProofQuotePool?: EpochProofQuotePool;
} = {},
deps: P2PClientDeps<T> = {},
) => {
let config = { ..._config };
const logger = createLogger('p2p');
const store = deps.store ?? (await createStore('p2p', config, createLogger('p2p:lmdb')));

const mempools: MemPools = {
const mempools: MemPools<T> = {
txPool: deps.txPool ?? new AztecKVTxPool(store, telemetry),
attestationPool: deps.attestationPool ?? new InMemoryAttestationPool(telemetry),
epochProofQuotePool: deps.epochProofQuotePool ?? new MemoryEpochProofQuotePool(telemetry),
attestationPool:
clientType === P2PClientType.Full
? ((deps.attestationPool ?? new InMemoryAttestationPool(telemetry)) as T extends P2PClientType.Full
? AttestationPool
: undefined)
: undefined,
};

let p2pService;
Expand All @@ -55,7 +68,8 @@ export const createP2PClient = async (
const peerId = await createLibP2PPeerIdFromPrivateKey(peerIdPrivateKey);
const discoveryService = new DiscV5Service(peerId, config, telemetry);

p2pService = await LibP2PService.new(
p2pService = await LibP2PService.new<T>(
clientType,
config,
discoveryService,
peerId,
Expand All @@ -70,5 +84,13 @@ export const createP2PClient = async (
logger.verbose('P2P is disabled. Using dummy P2P service');
p2pService = new DummyP2PService();
}
return new P2PClient(store, l2BlockSource, mempools, p2pService, config.keepProvenTxsInPoolFor, telemetry);
return new P2PClient(
clientType,
store,
l2BlockSource,
mempools,
p2pService,
config.keepProvenTxsInPoolFor,
telemetry,
);
};
20 changes: 10 additions & 10 deletions yarn-project/p2p/src/client/p2p_client.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { MockL2BlockSource } from '@aztec/archiver/test';
import { L2Block, mockEpochProofQuote, mockTx } from '@aztec/circuit-types';
import { L2Block, P2PClientType, mockEpochProofQuote, mockTx } from '@aztec/circuit-types';
import { Fr } from '@aztec/circuits.js';
import { retryUntil } from '@aztec/foundation/retry';
import { sleep } from '@aztec/foundation/sleep';
Expand All @@ -19,11 +19,11 @@ describe('In-Memory P2P Client', () => {
let txPool: MockProxy<TxPool>;
let attestationPool: MockProxy<AttestationPool>;
let epochProofQuotePool: MockProxy<EpochProofQuotePool>;
let mempools: MemPools;
let mempools: MemPools<P2PClientType.Full>;
let blockSource: MockL2BlockSource;
let p2pService: MockProxy<P2PService>;
let kvStore: AztecKVStore;
let client: P2PClient;
let client: P2PClient<P2PClientType.Full>;

beforeEach(() => {
txPool = mock<TxPool>();
Expand All @@ -49,7 +49,7 @@ describe('In-Memory P2P Client', () => {
};

kvStore = openTmpStore();
client = new P2PClient(kvStore, blockSource, mempools, p2pService, 0);
client = new P2PClient(P2PClientType.Full, kvStore, blockSource, mempools, p2pService, 0);
});

const advanceToProvenBlock = async (getProvenBlockNumber: number, provenEpochNumber = getProvenBlockNumber) => {
Expand Down Expand Up @@ -119,7 +119,7 @@ describe('In-Memory P2P Client', () => {
await client.start();
await client.stop();

const client2 = new P2PClient(kvStore, blockSource, mempools, p2pService, 0);
const client2 = new P2PClient(P2PClientType.Full, kvStore, blockSource, mempools, p2pService, 0);
expect(client2.getSyncedLatestBlockNum()).toEqual(client.getSyncedLatestBlockNum());
});

Expand All @@ -134,7 +134,7 @@ describe('In-Memory P2P Client', () => {
});

it('deletes txs after waiting the set number of blocks', async () => {
client = new P2PClient(kvStore, blockSource, mempools, p2pService, 10);
client = new P2PClient(P2PClientType.Full, kvStore, blockSource, mempools, p2pService, 10);
blockSource.setProvenBlockNumber(0);
await client.start();
expect(txPool.deleteTxs).not.toHaveBeenCalled();
Expand All @@ -151,7 +151,7 @@ describe('In-Memory P2P Client', () => {
});

it('stores and returns epoch proof quotes', async () => {
client = new P2PClient(kvStore, blockSource, mempools, p2pService, 0);
client = new P2PClient(P2PClientType.Full, kvStore, blockSource, mempools, p2pService, 0);

blockSource.setProvenEpochNumber(2);
await client.start();
Expand Down Expand Up @@ -182,7 +182,7 @@ describe('In-Memory P2P Client', () => {
});

it('deletes expired proof quotes', async () => {
client = new P2PClient(kvStore, blockSource, mempools, p2pService, 0);
client = new P2PClient(P2PClientType.Full, kvStore, blockSource, mempools, p2pService, 0);

blockSource.setProvenEpochNumber(1);
blockSource.setProvenBlockNumber(1);
Expand Down Expand Up @@ -245,7 +245,7 @@ describe('In-Memory P2P Client', () => {
});

it('deletes txs created from a pruned block', async () => {
client = new P2PClient(kvStore, blockSource, mempools, p2pService, 10);
client = new P2PClient(P2PClientType.Full, kvStore, blockSource, mempools, p2pService, 10);
blockSource.setProvenBlockNumber(0);
await client.start();

Expand All @@ -267,7 +267,7 @@ describe('In-Memory P2P Client', () => {
});

it('moves mined and valid txs back to the pending set', async () => {
client = new P2PClient(kvStore, blockSource, mempools, p2pService, 10);
client = new P2PClient(P2PClientType.Full, kvStore, blockSource, mempools, p2pService, 10);
blockSource.setProvenBlockNumber(0);
await client.start();

Expand Down
Loading
Loading