@aztec/p2p 0.76.4-devnet-test → 0.76.4-devnet-test-rc3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dest/client/factory.d.ts +2 -0
- package/dest/client/factory.d.ts.map +1 -1
- package/dest/client/factory.js +3 -1
- package/dest/client/p2p_client.d.ts +22 -1
- package/dest/client/p2p_client.d.ts.map +1 -1
- package/dest/client/p2p_client.js +23 -1
- package/dest/index.d.ts +3 -2
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +4 -3
- package/dest/mem_pools/epoch_proof_quote_pool/epoch_proof_quote_pool.d.ts +7 -0
- package/dest/mem_pools/epoch_proof_quote_pool/epoch_proof_quote_pool.d.ts.map +1 -0
- package/dest/mem_pools/epoch_proof_quote_pool/epoch_proof_quote_pool.js +2 -0
- package/dest/mem_pools/epoch_proof_quote_pool/index.d.ts +4 -0
- package/dest/mem_pools/epoch_proof_quote_pool/index.d.ts.map +1 -0
- package/dest/mem_pools/epoch_proof_quote_pool/index.js +4 -0
- package/dest/mem_pools/epoch_proof_quote_pool/memory_epoch_proof_quote_pool.d.ts +12 -0
- package/dest/mem_pools/epoch_proof_quote_pool/memory_epoch_proof_quote_pool.d.ts.map +1 -0
- package/dest/mem_pools/epoch_proof_quote_pool/memory_epoch_proof_quote_pool.js +30 -0
- package/dest/mem_pools/epoch_proof_quote_pool/test_utils.d.ts +8 -0
- package/dest/mem_pools/epoch_proof_quote_pool/test_utils.d.ts.map +1 -0
- package/dest/mem_pools/epoch_proof_quote_pool/test_utils.js +21 -0
- package/dest/mem_pools/index.d.ts +2 -1
- package/dest/mem_pools/index.d.ts.map +1 -1
- package/dest/mem_pools/instrumentation.d.ts +2 -1
- package/dest/mem_pools/instrumentation.d.ts.map +1 -1
- package/dest/mem_pools/instrumentation.js +8 -1
- package/dest/mem_pools/interface.d.ts +2 -0
- package/dest/mem_pools/interface.d.ts.map +1 -1
- package/dest/msg_validators/epoch_proof_quote_validator/epoch_proof_quote_validator.d.ts +8 -0
- package/dest/msg_validators/epoch_proof_quote_validator/epoch_proof_quote_validator.d.ts.map +1 -0
- package/dest/msg_validators/epoch_proof_quote_validator/epoch_proof_quote_validator.js +16 -0
- package/dest/msg_validators/epoch_proof_quote_validator/index.d.ts +2 -0
- package/dest/msg_validators/epoch_proof_quote_validator/index.d.ts.map +1 -0
- package/dest/msg_validators/epoch_proof_quote_validator/index.js +2 -0
- package/dest/services/libp2p/libp2p_service.d.ts +17 -1
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
- package/dest/services/libp2p/libp2p_service.js +55 -2
- package/dest/test-helpers/make-test-p2p-clients.d.ts +3 -1
- package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -1
- package/dest/test-helpers/make-test-p2p-clients.js +3 -2
- package/dest/testbench/p2p_client_testbench_worker.js +10 -1
- package/package.json +9 -9
- package/src/client/factory.ts +4 -0
- package/src/client/p2p_client.ts +44 -0
- package/src/index.ts +3 -2
- package/src/mem_pools/epoch_proof_quote_pool/epoch_proof_quote_pool.ts +7 -0
- package/src/mem_pools/epoch_proof_quote_pool/index.ts +3 -0
- package/src/mem_pools/epoch_proof_quote_pool/memory_epoch_proof_quote_pool.ts +41 -0
- package/src/mem_pools/epoch_proof_quote_pool/test_utils.ts +26 -0
- package/src/mem_pools/index.ts +2 -1
- package/src/mem_pools/instrumentation.ts +6 -0
- package/src/mem_pools/interface.ts +2 -0
- package/src/msg_validators/epoch_proof_quote_validator/epoch_proof_quote_validator.ts +22 -0
- package/src/msg_validators/epoch_proof_quote_validator/index.ts +1 -0
- package/src/services/libp2p/libp2p_service.ts +63 -0
- package/src/test-helpers/make-test-p2p-clients.ts +4 -0
- package/src/testbench/p2p_client_testbench_worker.ts +11 -0
package/src/client/p2p_client.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
type BlockAttestation,
|
|
3
3
|
type BlockProposal,
|
|
4
|
+
type EpochProofQuote,
|
|
4
5
|
type L2Block,
|
|
5
6
|
type L2BlockId,
|
|
6
7
|
type L2BlockSource,
|
|
@@ -29,6 +30,7 @@ import { type ENR } from '@chainsafe/enr';
|
|
|
29
30
|
|
|
30
31
|
import { type P2PConfig, getP2PDefaultConfig } from '../config.js';
|
|
31
32
|
import { type AttestationPool } from '../mem_pools/attestation_pool/attestation_pool.js';
|
|
33
|
+
import { type EpochProofQuotePool } from '../mem_pools/epoch_proof_quote_pool/epoch_proof_quote_pool.js';
|
|
32
34
|
import { type MemPools } from '../mem_pools/interface.js';
|
|
33
35
|
import { type TxPool } from '../mem_pools/tx_pool/index.js';
|
|
34
36
|
import { ReqRespSubProtocol } from '../services/reqresp/interface.js';
|
|
@@ -70,6 +72,21 @@ export type P2P<T extends P2PClientType = P2PClientType.Full> = ProverCoordinati
|
|
|
70
72
|
*/
|
|
71
73
|
broadcastProposal(proposal: BlockProposal): void;
|
|
72
74
|
|
|
75
|
+
/**
|
|
76
|
+
* Queries the EpochProofQuote pool for quotes for the given epoch
|
|
77
|
+
*
|
|
78
|
+
* @param epoch - the epoch to query
|
|
79
|
+
* @returns EpochProofQuotes
|
|
80
|
+
*/
|
|
81
|
+
getEpochProofQuotes(epoch: bigint): Promise<EpochProofQuote[]>;
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Adds an EpochProofQuote to the pool and broadcasts an EpochProofQuote to other peers.
|
|
85
|
+
*
|
|
86
|
+
* @param quote - the quote to broadcast
|
|
87
|
+
*/
|
|
88
|
+
addEpochProofQuote(quote: EpochProofQuote): Promise<void>;
|
|
89
|
+
|
|
73
90
|
/**
|
|
74
91
|
* Registers a callback from the validator client that determines how to behave when
|
|
75
92
|
* foreign block proposals are received
|
|
@@ -194,6 +211,7 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
|
|
|
194
211
|
|
|
195
212
|
private txPool: TxPool;
|
|
196
213
|
private attestationPool: T extends P2PClientType.Full ? AttestationPool : undefined;
|
|
214
|
+
private epochProofQuotePool: EpochProofQuotePool;
|
|
197
215
|
|
|
198
216
|
/** How many slots to keep attestations for. */
|
|
199
217
|
private keepAttestationsInPoolFor: number;
|
|
@@ -242,6 +260,7 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
|
|
|
242
260
|
this.synchedProvenBlockNumber = store.openSingleton('p2p_pool_last_proven_l2_block');
|
|
243
261
|
|
|
244
262
|
this.txPool = mempools.txPool;
|
|
263
|
+
this.epochProofQuotePool = mempools.epochProofQuotePool;
|
|
245
264
|
this.attestationPool = mempools.attestationPool!;
|
|
246
265
|
}
|
|
247
266
|
|
|
@@ -318,6 +337,26 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
|
|
|
318
337
|
}
|
|
319
338
|
}
|
|
320
339
|
|
|
340
|
+
/**
|
|
341
|
+
* Adds an EpochProofQuote to the pool and broadcasts an EpochProofQuote to other peers.
|
|
342
|
+
* @param quote - the quote to broadcast
|
|
343
|
+
*/
|
|
344
|
+
addEpochProofQuote(quote: EpochProofQuote): Promise<void> {
|
|
345
|
+
this.epochProofQuotePool.addQuote(quote);
|
|
346
|
+
this.broadcastEpochProofQuote(quote);
|
|
347
|
+
return Promise.resolve();
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
getEpochProofQuotes(epoch: bigint): Promise<EpochProofQuote[]> {
|
|
351
|
+
return Promise.resolve(this.epochProofQuotePool.getQuotes(epoch));
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
broadcastEpochProofQuote(quote: EpochProofQuote): void {
|
|
355
|
+
this.#assertIsReady();
|
|
356
|
+
this.log.info('Broadcasting epoch proof quote', quote.toViemArgs());
|
|
357
|
+
return this.p2pService.propagate(quote);
|
|
358
|
+
}
|
|
359
|
+
|
|
321
360
|
/**
|
|
322
361
|
* Starts the P2P client.
|
|
323
362
|
* @returns An empty promise signalling the synching process.
|
|
@@ -692,6 +731,11 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
|
|
|
692
731
|
await this.attestationPool?.deleteAttestationsOlderThan(lastBlockSlotMinusKeepAttestationsInPoolFor);
|
|
693
732
|
}
|
|
694
733
|
|
|
734
|
+
const provenEpochNumber = await this.l2BlockSource.getProvenL2EpochNumber();
|
|
735
|
+
if (provenEpochNumber !== undefined) {
|
|
736
|
+
this.epochProofQuotePool.deleteQuotesToEpoch(BigInt(provenEpochNumber));
|
|
737
|
+
}
|
|
738
|
+
|
|
695
739
|
await this.synchedProvenBlockNumber.set(lastBlockNum);
|
|
696
740
|
this.log.debug(`Synched to proven block ${lastBlockNum}`);
|
|
697
741
|
|
package/src/index.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
export * from './mem_pools/attestation_pool/index.js';
|
|
1
2
|
export * from './bootstrap/bootstrap.js';
|
|
2
3
|
export * from './client/index.js';
|
|
3
4
|
export * from './config.js';
|
|
4
|
-
export * from './mem_pools/
|
|
5
|
+
export * from './mem_pools/epoch_proof_quote_pool/index.js';
|
|
6
|
+
export * from './services/index.js';
|
|
5
7
|
export * from './mem_pools/tx_pool/index.js';
|
|
6
8
|
export * from './msg_validators/index.js';
|
|
7
|
-
export * from './services/index.js';
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { type EpochProofQuote } from '@aztec/circuit-types';
|
|
2
|
+
import { type TelemetryClient, getTelemetryClient } from '@aztec/telemetry-client';
|
|
3
|
+
|
|
4
|
+
import { PoolInstrumentation, PoolName } from '../instrumentation.js';
|
|
5
|
+
import { type EpochProofQuotePool } from './epoch_proof_quote_pool.js';
|
|
6
|
+
|
|
7
|
+
export class MemoryEpochProofQuotePool implements EpochProofQuotePool {
|
|
8
|
+
private quotes: Map<bigint, EpochProofQuote[]>;
|
|
9
|
+
private metrics: PoolInstrumentation<EpochProofQuote>;
|
|
10
|
+
|
|
11
|
+
constructor(telemetry: TelemetryClient = getTelemetryClient()) {
|
|
12
|
+
this.quotes = new Map();
|
|
13
|
+
this.metrics = new PoolInstrumentation(telemetry, PoolName.EPOCH_PROOF_QUOTE_POOL);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
addQuote(quote: EpochProofQuote) {
|
|
17
|
+
const epoch = quote.payload.epochToProve;
|
|
18
|
+
if (!this.quotes.has(epoch)) {
|
|
19
|
+
this.quotes.set(epoch, []);
|
|
20
|
+
}
|
|
21
|
+
this.quotes.get(epoch)!.push(quote);
|
|
22
|
+
|
|
23
|
+
this.metrics.recordAddedObjects(1);
|
|
24
|
+
}
|
|
25
|
+
getQuotes(epoch: bigint): EpochProofQuote[] {
|
|
26
|
+
return this.quotes.get(epoch) || [];
|
|
27
|
+
}
|
|
28
|
+
deleteQuotesToEpoch(epoch: bigint): void {
|
|
29
|
+
const expiredEpochs = Array.from(this.quotes.keys()).filter(k => k <= epoch);
|
|
30
|
+
|
|
31
|
+
let removedObjectsCount = 0;
|
|
32
|
+
for (const expiredEpoch of expiredEpochs) {
|
|
33
|
+
// For logging
|
|
34
|
+
removedObjectsCount += this.quotes.get(expiredEpoch)?.length || 0;
|
|
35
|
+
|
|
36
|
+
this.quotes.delete(expiredEpoch);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
this.metrics.recordRemovedObjects(removedObjectsCount);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { EpochProofQuote, EpochProofQuotePayload } from '@aztec/circuit-types';
|
|
2
|
+
import { EthAddress } from '@aztec/circuits.js';
|
|
3
|
+
import { Buffer32 } from '@aztec/foundation/buffer';
|
|
4
|
+
import { Secp256k1Signer, randomBigInt, randomInt } from '@aztec/foundation/crypto';
|
|
5
|
+
|
|
6
|
+
export function makeRandomEpochProofQuotePayload(): EpochProofQuotePayload {
|
|
7
|
+
return EpochProofQuotePayload.from({
|
|
8
|
+
basisPointFee: randomInt(10000),
|
|
9
|
+
bondAmount: 1000000000000000000n,
|
|
10
|
+
epochToProve: randomBigInt(1000000n),
|
|
11
|
+
prover: EthAddress.random(),
|
|
12
|
+
validUntilSlot: randomBigInt(1000000n),
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function makeRandomEpochProofQuote(payload?: EpochProofQuotePayload): {
|
|
17
|
+
quote: EpochProofQuote;
|
|
18
|
+
signer: Secp256k1Signer;
|
|
19
|
+
} {
|
|
20
|
+
const signer = Secp256k1Signer.random();
|
|
21
|
+
|
|
22
|
+
return {
|
|
23
|
+
quote: EpochProofQuote.new(Buffer32.random(), payload ?? makeRandomEpochProofQuotePayload(), signer),
|
|
24
|
+
signer,
|
|
25
|
+
};
|
|
26
|
+
}
|
package/src/mem_pools/index.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export { TxPool } from './tx_pool/tx_pool.js';
|
|
1
2
|
export { AttestationPool } from './attestation_pool/attestation_pool.js';
|
|
3
|
+
export { EpochProofQuotePool } from './epoch_proof_quote_pool/epoch_proof_quote_pool.js';
|
|
2
4
|
export { type MemPools } from './interface.js';
|
|
3
|
-
export { TxPool } from './tx_pool/tx_pool.js';
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
export enum PoolName {
|
|
13
13
|
TX_POOL = 'TxPool',
|
|
14
14
|
ATTESTATION_POOL = 'AttestationPool',
|
|
15
|
+
EPOCH_PROOF_QUOTE_POOL = 'EpochProofQuotePool',
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
type MetricsLabels = {
|
|
@@ -35,6 +36,11 @@ function getMetricsLabels(name: PoolName): MetricsLabels {
|
|
|
35
36
|
objectInMempool: Metrics.MEMPOOL_ATTESTATIONS_COUNT,
|
|
36
37
|
objectSize: Metrics.MEMPOOL_ATTESTATIONS_SIZE,
|
|
37
38
|
};
|
|
39
|
+
} else if (name === PoolName.EPOCH_PROOF_QUOTE_POOL) {
|
|
40
|
+
return {
|
|
41
|
+
objectInMempool: Metrics.MEMPOOL_PROVER_QUOTE_COUNT,
|
|
42
|
+
objectSize: Metrics.MEMPOOL_PROVER_QUOTE_SIZE,
|
|
43
|
+
};
|
|
38
44
|
}
|
|
39
45
|
|
|
40
46
|
throw new Error('Invalid pool type');
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type P2PClientType } from '@aztec/circuit-types';
|
|
2
2
|
|
|
3
3
|
import { type AttestationPool } from './attestation_pool/attestation_pool.js';
|
|
4
|
+
import { type EpochProofQuotePool } from './epoch_proof_quote_pool/epoch_proof_quote_pool.js';
|
|
4
5
|
import { type TxPool } from './tx_pool/tx_pool.js';
|
|
5
6
|
|
|
6
7
|
/**
|
|
@@ -9,4 +10,5 @@ import { type TxPool } from './tx_pool/tx_pool.js';
|
|
|
9
10
|
export type MemPools<T extends P2PClientType = P2PClientType.Full> = {
|
|
10
11
|
txPool: TxPool;
|
|
11
12
|
attestationPool?: T extends P2PClientType.Full ? AttestationPool : undefined;
|
|
13
|
+
epochProofQuotePool: EpochProofQuotePool;
|
|
12
14
|
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type EpochProofQuote, type P2PValidator, PeerErrorSeverity } from '@aztec/circuit-types';
|
|
2
|
+
import { type EpochCacheInterface } from '@aztec/epoch-cache';
|
|
3
|
+
|
|
4
|
+
export class EpochProofQuoteValidator implements P2PValidator<EpochProofQuote> {
|
|
5
|
+
private epochCache: EpochCacheInterface;
|
|
6
|
+
|
|
7
|
+
constructor(epochCache: EpochCacheInterface) {
|
|
8
|
+
this.epochCache = epochCache;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
validate(message: EpochProofQuote): Promise<PeerErrorSeverity | undefined> {
|
|
12
|
+
const { epoch } = this.epochCache.getEpochAndSlotNow();
|
|
13
|
+
|
|
14
|
+
// Check that the epoch proof quote is for the current epoch
|
|
15
|
+
const epochToProve = message.payload.epochToProve;
|
|
16
|
+
if (epochToProve !== epoch && epochToProve !== epoch - 1n) {
|
|
17
|
+
return Promise.resolve(PeerErrorSeverity.HighToleranceError);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return Promise.resolve(undefined);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { EpochProofQuoteValidator } from './epoch_proof_quote_validator.js';
|
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
BlockAttestation,
|
|
3
3
|
BlockProposal,
|
|
4
4
|
type ClientProtocolCircuitVerifier,
|
|
5
|
+
EpochProofQuote,
|
|
5
6
|
type Gossipable,
|
|
6
7
|
type L2BlockSource,
|
|
7
8
|
MerkleTreeId,
|
|
@@ -47,6 +48,7 @@ import { createLibp2p } from 'libp2p';
|
|
|
47
48
|
|
|
48
49
|
import { type P2PConfig } from '../../config.js';
|
|
49
50
|
import { type MemPools } from '../../mem_pools/interface.js';
|
|
51
|
+
import { EpochProofQuoteValidator } from '../../msg_validators/epoch_proof_quote_validator/index.js';
|
|
50
52
|
import { AttestationValidator, BlockProposalValidator } from '../../msg_validators/index.js';
|
|
51
53
|
import {
|
|
52
54
|
DataTxValidator,
|
|
@@ -93,6 +95,7 @@ export class LibP2PService<T extends P2PClientType> extends WithTracer implement
|
|
|
93
95
|
// Message validators
|
|
94
96
|
private attestationValidator: AttestationValidator;
|
|
95
97
|
private blockProposalValidator: BlockProposalValidator;
|
|
98
|
+
private epochProofQuoteValidator: EpochProofQuoteValidator;
|
|
96
99
|
|
|
97
100
|
// Request and response sub service
|
|
98
101
|
public reqresp: ReqResp;
|
|
@@ -140,6 +143,7 @@ export class LibP2PService<T extends P2PClientType> extends WithTracer implement
|
|
|
140
143
|
|
|
141
144
|
this.attestationValidator = new AttestationValidator(epochCache);
|
|
142
145
|
this.blockProposalValidator = new BlockProposalValidator(epochCache);
|
|
146
|
+
this.epochProofQuoteValidator = new EpochProofQuoteValidator(epochCache);
|
|
143
147
|
|
|
144
148
|
this.blockReceivedCallback = async (block: BlockProposal): Promise<BlockAttestation | undefined> => {
|
|
145
149
|
this.logger.warn(
|
|
@@ -261,6 +265,11 @@ export class LibP2PService<T extends P2PClientType> extends WithTracer implement
|
|
|
261
265
|
invalidMessageDeliveriesWeight: -20,
|
|
262
266
|
invalidMessageDeliveriesDecay: 0.5,
|
|
263
267
|
}),
|
|
268
|
+
[EpochProofQuote.p2pTopic]: createTopicScoreParams({
|
|
269
|
+
topicWeight: 1,
|
|
270
|
+
invalidMessageDeliveriesWeight: -20,
|
|
271
|
+
invalidMessageDeliveriesDecay: 0.5,
|
|
272
|
+
}),
|
|
264
273
|
},
|
|
265
274
|
}),
|
|
266
275
|
}) as (components: GossipSubComponents) => GossipSub,
|
|
@@ -334,6 +343,7 @@ export class LibP2PService<T extends P2PClientType> extends WithTracer implement
|
|
|
334
343
|
[Tx.p2pTopic]: this.validatePropagatedTxFromMessage.bind(this),
|
|
335
344
|
[BlockAttestation.p2pTopic]: this.validatePropagatedAttestationFromMessage.bind(this),
|
|
336
345
|
[BlockProposal.p2pTopic]: this.validatePropagatedBlockFromMessage.bind(this),
|
|
346
|
+
[EpochProofQuote.p2pTopic]: this.validatePropagatedEpochProofQuoteFromMessage.bind(this),
|
|
337
347
|
};
|
|
338
348
|
// When running bandwidth benchmarks, we use send blobs of data we do not want to validate
|
|
339
349
|
// NEVER switch this off in production
|
|
@@ -497,6 +507,10 @@ export class LibP2PService<T extends P2PClientType> extends WithTracer implement
|
|
|
497
507
|
const block = BlockProposal.fromBuffer(Buffer.from(message.data));
|
|
498
508
|
await this.processBlockFromPeer(block);
|
|
499
509
|
}
|
|
510
|
+
if (message.topic == EpochProofQuote.p2pTopic) {
|
|
511
|
+
const epochProofQuote = EpochProofQuote.fromBuffer(Buffer.from(message.data));
|
|
512
|
+
await this.processEpochProofQuoteFromPeer(epochProofQuote);
|
|
513
|
+
}
|
|
500
514
|
|
|
501
515
|
return;
|
|
502
516
|
}
|
|
@@ -580,6 +594,17 @@ export class LibP2PService<T extends P2PClientType> extends WithTracer implement
|
|
|
580
594
|
await this.propagate(attestation);
|
|
581
595
|
}
|
|
582
596
|
|
|
597
|
+
private async processEpochProofQuoteFromPeer(epochProofQuote: EpochProofQuote) {
|
|
598
|
+
const epoch = epochProofQuote.payload.epochToProve;
|
|
599
|
+
const prover = epochProofQuote.payload.prover.toString();
|
|
600
|
+
const p2pMessageIdentifier = await epochProofQuote.p2pMessageIdentifier();
|
|
601
|
+
this.logger.verbose(
|
|
602
|
+
`Received epoch proof quote ${p2pMessageIdentifier} by prover ${prover} for epoch ${epoch} from external peer.`,
|
|
603
|
+
{ quote: epochProofQuote.toInspect(), p2pMessageIdentifier },
|
|
604
|
+
);
|
|
605
|
+
this.mempools.epochProofQuotePool.addQuote(epochProofQuote);
|
|
606
|
+
}
|
|
607
|
+
|
|
583
608
|
/**
|
|
584
609
|
* Propagates provided message to peers.
|
|
585
610
|
* @param message - The message to propagate.
|
|
@@ -693,6 +718,25 @@ export class LibP2PService<T extends P2PClientType> extends WithTracer implement
|
|
|
693
718
|
return isValid ? TopicValidatorResult.Accept : TopicValidatorResult.Reject;
|
|
694
719
|
}
|
|
695
720
|
|
|
721
|
+
/**
|
|
722
|
+
* Validate an epoch proof quote from a peer.
|
|
723
|
+
* @param propagationSource - The peer ID of the peer that sent the epoch proof quote.
|
|
724
|
+
* @param msg - The epoch proof quote message.
|
|
725
|
+
* @returns True if the epoch proof quote is valid, false otherwise.
|
|
726
|
+
*/
|
|
727
|
+
private async validatePropagatedEpochProofQuoteFromMessage(
|
|
728
|
+
propagationSource: PeerId,
|
|
729
|
+
msg: Message,
|
|
730
|
+
): Promise<TopicValidatorResult> {
|
|
731
|
+
const epochProofQuote = EpochProofQuote.fromBuffer(Buffer.from(msg.data));
|
|
732
|
+
const isValid = await this.validateEpochProofQuote(propagationSource, epochProofQuote);
|
|
733
|
+
this.logger.trace(`validatePropagatedEpochProofQuote: ${isValid}`, {
|
|
734
|
+
[Attributes.EPOCH_NUMBER]: epochProofQuote.payload.epochToProve.toString(),
|
|
735
|
+
[Attributes.P2P_ID]: propagationSource.toString(),
|
|
736
|
+
});
|
|
737
|
+
return isValid ? TopicValidatorResult.Accept : TopicValidatorResult.Reject;
|
|
738
|
+
}
|
|
739
|
+
|
|
696
740
|
@trackSpan('Libp2pService.validatePropagatedTx', async tx => ({
|
|
697
741
|
[Attributes.TX_HASH]: (await tx.getTxHash()).toString(),
|
|
698
742
|
}))
|
|
@@ -864,6 +908,25 @@ export class LibP2PService<T extends P2PClientType> extends WithTracer implement
|
|
|
864
908
|
return true;
|
|
865
909
|
}
|
|
866
910
|
|
|
911
|
+
/**
|
|
912
|
+
* Validate an epoch proof quote.
|
|
913
|
+
*
|
|
914
|
+
* @param epochProofQuote - The epoch proof quote to validate.
|
|
915
|
+
* @returns True if the epoch proof quote is valid, false otherwise.
|
|
916
|
+
*/
|
|
917
|
+
@trackSpan('Libp2pService.validateEpochProofQuote', (_peerId, epochProofQuote) => ({
|
|
918
|
+
[Attributes.EPOCH_NUMBER]: epochProofQuote.payload.epochToProve.toString(),
|
|
919
|
+
}))
|
|
920
|
+
public async validateEpochProofQuote(peerId: PeerId, epochProofQuote: EpochProofQuote): Promise<boolean> {
|
|
921
|
+
const severity = await this.epochProofQuoteValidator.validate(epochProofQuote);
|
|
922
|
+
if (severity) {
|
|
923
|
+
this.peerManager.penalizePeer(peerId, severity);
|
|
924
|
+
return false;
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
return true;
|
|
928
|
+
}
|
|
929
|
+
|
|
867
930
|
public getPeerScore(peerId: PeerId): number {
|
|
868
931
|
return this.node.services.pubsub.score.score(peerId.toString());
|
|
869
932
|
}
|
|
@@ -9,6 +9,7 @@ import { createP2PClient } from '../client/index.js';
|
|
|
9
9
|
import { type P2PClient } from '../client/p2p_client.js';
|
|
10
10
|
import { type P2PConfig } from '../config.js';
|
|
11
11
|
import { type AttestationPool } from '../mem_pools/attestation_pool/attestation_pool.js';
|
|
12
|
+
import { type EpochProofQuotePool } from '../mem_pools/epoch_proof_quote_pool/epoch_proof_quote_pool.js';
|
|
12
13
|
import { type TxPool } from '../mem_pools/tx_pool/index.js';
|
|
13
14
|
import { generatePeerIdPrivateKeys } from '../test-helpers/generate-peer-id-private-keys.js';
|
|
14
15
|
import { getPorts } from './get-ports.js';
|
|
@@ -17,6 +18,7 @@ import { AlwaysFalseCircuitVerifier, AlwaysTrueCircuitVerifier } from './reqresp
|
|
|
17
18
|
|
|
18
19
|
interface MakeTestP2PClientOptions {
|
|
19
20
|
mockAttestationPool: AttestationPool;
|
|
21
|
+
mockEpochProofQuotePool: EpochProofQuotePool;
|
|
20
22
|
mockTxPool: TxPool;
|
|
21
23
|
mockEpochCache: EpochCache;
|
|
22
24
|
mockWorldState: WorldStateSynchronizer;
|
|
@@ -43,6 +45,7 @@ export async function makeTestP2PClient(
|
|
|
43
45
|
p2pBaseConfig,
|
|
44
46
|
p2pConfigOverrides = {},
|
|
45
47
|
mockAttestationPool,
|
|
48
|
+
mockEpochProofQuotePool,
|
|
46
49
|
mockTxPool,
|
|
47
50
|
mockEpochCache,
|
|
48
51
|
mockWorldState,
|
|
@@ -76,6 +79,7 @@ export async function makeTestP2PClient(
|
|
|
76
79
|
const deps = {
|
|
77
80
|
txPool: mockTxPool as unknown as TxPool,
|
|
78
81
|
attestationPool: mockAttestationPool as unknown as AttestationPool,
|
|
82
|
+
epochProofQuotePool: mockEpochProofQuotePool as unknown as EpochProofQuotePool,
|
|
79
83
|
store: kvStore,
|
|
80
84
|
logger,
|
|
81
85
|
};
|
|
@@ -15,6 +15,7 @@ import { openTmpStore } from '@aztec/kv-store/lmdb-v2';
|
|
|
15
15
|
import { type P2PConfig } from '../config.js';
|
|
16
16
|
import { createP2PClient } from '../index.js';
|
|
17
17
|
import { type AttestationPool } from '../mem_pools/attestation_pool/attestation_pool.js';
|
|
18
|
+
import { type EpochProofQuotePool } from '../mem_pools/epoch_proof_quote_pool/epoch_proof_quote_pool.js';
|
|
18
19
|
import { type TxPool } from '../mem_pools/tx_pool/index.js';
|
|
19
20
|
import { AlwaysTrueCircuitVerifier } from '../test-helpers/reqresp-nodes.js';
|
|
20
21
|
|
|
@@ -47,6 +48,14 @@ function mockAttestationPool(): AttestationPool {
|
|
|
47
48
|
};
|
|
48
49
|
}
|
|
49
50
|
|
|
51
|
+
function mockEpochProofQuotePool(): EpochProofQuotePool {
|
|
52
|
+
return {
|
|
53
|
+
addQuote: () => {},
|
|
54
|
+
getQuotes: () => [],
|
|
55
|
+
deleteQuotesToEpoch: () => {},
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
50
59
|
function mockEpochCache(): EpochCacheInterface {
|
|
51
60
|
return {
|
|
52
61
|
getCommittee: () => Promise.resolve([] as EthAddress[]),
|
|
@@ -72,6 +81,7 @@ process.on('message', async msg => {
|
|
|
72
81
|
if (type === 'START') {
|
|
73
82
|
const txPool = mockTxPool();
|
|
74
83
|
const attestationPool = mockAttestationPool();
|
|
84
|
+
const epochProofQuotePool = mockEpochProofQuotePool();
|
|
75
85
|
const epochCache = mockEpochCache();
|
|
76
86
|
const worldState = {} as WorldStateSynchronizer;
|
|
77
87
|
const l2BlockSource = new MockL2BlockSource();
|
|
@@ -84,6 +94,7 @@ process.on('message', async msg => {
|
|
|
84
94
|
const deps = {
|
|
85
95
|
txPool,
|
|
86
96
|
attestationPool,
|
|
97
|
+
epochProofQuotePool,
|
|
87
98
|
store: kvStore,
|
|
88
99
|
logger,
|
|
89
100
|
};
|