@aztec/p2p 4.0.0-nightly.20260111 → 4.0.0-nightly.20260113
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/interface.d.ts +18 -5
- package/dest/client/interface.d.ts.map +1 -1
- package/dest/client/p2p_client.d.ts +9 -12
- package/dest/client/p2p_client.d.ts.map +1 -1
- package/dest/client/p2p_client.js +59 -103
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +61 -42
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.js +225 -262
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts +21 -18
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.js +113 -108
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts +17 -16
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.js +89 -128
- package/dest/mem_pools/attestation_pool/mocks.d.ts +7 -6
- package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/mocks.js +9 -8
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +4 -4
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -1
- package/dest/msg_validators/attestation_validator/attestation_validator.js +12 -10
- package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts +5 -5
- package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts.map +1 -1
- package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.js +5 -5
- package/dest/msg_validators/index.d.ts +2 -2
- package/dest/msg_validators/index.d.ts.map +1 -1
- package/dest/msg_validators/index.js +1 -1
- package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts +9 -0
- package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts.map +1 -0
- package/dest/msg_validators/proposal_validator/block_proposal_validator.js +6 -0
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts +9 -0
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts.map +1 -0
- package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.js +6 -0
- package/dest/msg_validators/proposal_validator/index.d.ts +4 -0
- package/dest/msg_validators/proposal_validator/index.d.ts.map +1 -0
- package/dest/msg_validators/proposal_validator/index.js +3 -0
- package/dest/msg_validators/proposal_validator/proposal_validator.d.ts +13 -0
- package/dest/msg_validators/proposal_validator/proposal_validator.d.ts.map +1 -0
- package/dest/msg_validators/{block_proposal_validator/block_proposal_validator.js → proposal_validator/proposal_validator.js} +19 -21
- package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.d.ts +23 -0
- package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.d.ts.map +1 -0
- package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.js +183 -0
- package/dest/services/dummy_service.d.ts +6 -2
- package/dest/services/dummy_service.d.ts.map +1 -1
- package/dest/services/dummy_service.js +3 -0
- package/dest/services/encoding.d.ts +1 -1
- package/dest/services/encoding.d.ts.map +1 -1
- package/dest/services/encoding.js +4 -2
- package/dest/services/libp2p/libp2p_service.d.ts +26 -10
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
- package/dest/services/libp2p/libp2p_service.js +218 -88
- package/dest/services/service.d.ts +16 -3
- package/dest/services/service.d.ts.map +1 -1
- package/dest/testbench/p2p_client_testbench_worker.js +25 -11
- package/dest/testbench/worker_client_manager.d.ts +1 -1
- package/dest/testbench/worker_client_manager.d.ts.map +1 -1
- package/dest/testbench/worker_client_manager.js +6 -1
- package/package.json +14 -14
- package/src/client/interface.ts +19 -4
- package/src/client/p2p_client.ts +69 -110
- package/src/mem_pools/attestation_pool/attestation_pool.ts +68 -41
- package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +231 -287
- package/src/mem_pools/attestation_pool/kv_attestation_pool.ts +162 -140
- package/src/mem_pools/attestation_pool/memory_attestation_pool.ts +141 -164
- package/src/mem_pools/attestation_pool/mocks.ts +13 -9
- package/src/msg_validators/attestation_validator/attestation_validator.ts +16 -13
- package/src/msg_validators/attestation_validator/fisherman_attestation_validator.ts +7 -7
- package/src/msg_validators/index.ts +1 -1
- package/src/msg_validators/proposal_validator/block_proposal_validator.ts +10 -0
- package/src/msg_validators/proposal_validator/checkpoint_proposal_validator.ts +13 -0
- package/src/msg_validators/proposal_validator/index.ts +3 -0
- package/src/msg_validators/{block_proposal_validator/block_proposal_validator.ts → proposal_validator/proposal_validator.ts} +23 -28
- package/src/msg_validators/proposal_validator/proposal_validator_test_suite.ts +206 -0
- package/src/services/dummy_service.ts +6 -0
- package/src/services/encoding.ts +3 -1
- package/src/services/libp2p/libp2p_service.ts +258 -94
- package/src/services/service.ts +19 -4
- package/src/testbench/p2p_client_testbench_worker.ts +34 -11
- package/src/testbench/worker_client_manager.ts +6 -1
- package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts +0 -12
- package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts.map +0 -1
- package/dest/msg_validators/block_proposal_validator/index.d.ts +0 -2
- package/dest/msg_validators/block_proposal_validator/index.d.ts.map +0 -1
- package/dest/msg_validators/block_proposal_validator/index.js +0 -1
- package/src/msg_validators/block_proposal_validator/index.ts +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { EpochCacheInterface } from '@aztec/epoch-cache';
|
|
2
|
-
import { BlockNumber
|
|
2
|
+
import { BlockNumber } from '@aztec/foundation/branded-types';
|
|
3
3
|
import { randomInt } from '@aztec/foundation/crypto/random';
|
|
4
4
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
5
5
|
import { type Logger, createLibp2pComponentLogger, createLogger } from '@aztec/foundation/log';
|
|
@@ -13,8 +13,10 @@ import type { ContractDataSource } from '@aztec/stdlib/contract';
|
|
|
13
13
|
import { GasFees } from '@aztec/stdlib/gas';
|
|
14
14
|
import type { ClientProtocolCircuitVerifier, PeerInfo, WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
|
|
15
15
|
import {
|
|
16
|
-
BlockAttestation,
|
|
17
16
|
BlockProposal,
|
|
17
|
+
CheckpointAttestation,
|
|
18
|
+
CheckpointProposal,
|
|
19
|
+
type CheckpointProposalCore,
|
|
18
20
|
type Gossipable,
|
|
19
21
|
P2PClientType,
|
|
20
22
|
P2PMessage,
|
|
@@ -60,8 +62,9 @@ import type { P2PConfig } from '../../config.js';
|
|
|
60
62
|
import { ProposalSlotCapExceededError } from '../../errors/attestation-pool.error.js';
|
|
61
63
|
import type { MemPools } from '../../mem_pools/interface.js';
|
|
62
64
|
import {
|
|
63
|
-
AttestationValidator,
|
|
64
65
|
BlockProposalValidator,
|
|
66
|
+
CheckpointAttestationValidator,
|
|
67
|
+
CheckpointProposalValidator,
|
|
65
68
|
FishermanAttestationValidator,
|
|
66
69
|
} from '../../msg_validators/index.js';
|
|
67
70
|
import { MessageSeenValidator } from '../../msg_validators/msg_seen_validator/msg_seen_validator.js';
|
|
@@ -108,7 +111,12 @@ import {
|
|
|
108
111
|
reqRespTxHandler,
|
|
109
112
|
} from '../reqresp/protocols/index.js';
|
|
110
113
|
import { ReqResp } from '../reqresp/reqresp.js';
|
|
111
|
-
import type {
|
|
114
|
+
import type {
|
|
115
|
+
P2PBlockReceivedCallback,
|
|
116
|
+
P2PCheckpointReceivedCallback,
|
|
117
|
+
P2PService,
|
|
118
|
+
PeerDiscoveryService,
|
|
119
|
+
} from '../service.js';
|
|
112
120
|
import { P2PInstrumentation } from './instrumentation.js';
|
|
113
121
|
|
|
114
122
|
interface ValidationResult {
|
|
@@ -132,8 +140,9 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
132
140
|
private msgIdSeenValidators: Record<TopicType, MessageSeenValidator> = {} as Record<TopicType, MessageSeenValidator>;
|
|
133
141
|
|
|
134
142
|
// Message validators
|
|
135
|
-
private attestationValidator: AttestationValidator;
|
|
136
143
|
private blockProposalValidator: BlockProposalValidator;
|
|
144
|
+
private checkpointProposalValidator: CheckpointProposalValidator;
|
|
145
|
+
private checkpointAttestationValidator: CheckpointAttestationValidator;
|
|
137
146
|
|
|
138
147
|
private protocolVersion = '';
|
|
139
148
|
private topicStrings: Record<TopicType, string> = {} as Record<TopicType, string>;
|
|
@@ -147,6 +156,13 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
147
156
|
*/
|
|
148
157
|
private blockReceivedCallback: P2PBlockReceivedCallback;
|
|
149
158
|
|
|
159
|
+
/**
|
|
160
|
+
* Callback for when a checkpoint proposal is received from a peer.
|
|
161
|
+
* @param checkpoint - The checkpoint proposal received from the peer.
|
|
162
|
+
* @returns The attestations for the checkpoint, if any.
|
|
163
|
+
*/
|
|
164
|
+
private checkpointReceivedCallback: P2PCheckpointReceivedCallback;
|
|
165
|
+
|
|
150
166
|
private gossipSubEventHandler: (e: CustomEvent<GossipsubMessage>) => void;
|
|
151
167
|
|
|
152
168
|
private instrumentation: P2PInstrumentation;
|
|
@@ -180,7 +196,8 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
180
196
|
|
|
181
197
|
this.msgIdSeenValidators[TopicType.tx] = new MessageSeenValidator(config.seenMessageCacheSize);
|
|
182
198
|
this.msgIdSeenValidators[TopicType.block_proposal] = new MessageSeenValidator(config.seenMessageCacheSize);
|
|
183
|
-
this.msgIdSeenValidators[TopicType.
|
|
199
|
+
this.msgIdSeenValidators[TopicType.checkpoint_proposal] = new MessageSeenValidator(config.seenMessageCacheSize);
|
|
200
|
+
this.msgIdSeenValidators[TopicType.checkpoint_attestation] = new MessageSeenValidator(config.seenMessageCacheSize);
|
|
184
201
|
|
|
185
202
|
const versions = getVersions(config);
|
|
186
203
|
this.protocolVersion = compressComponentVersions(versions);
|
|
@@ -188,25 +205,40 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
188
205
|
|
|
189
206
|
this.topicStrings[TopicType.tx] = createTopicString(TopicType.tx, this.protocolVersion);
|
|
190
207
|
this.topicStrings[TopicType.block_proposal] = createTopicString(TopicType.block_proposal, this.protocolVersion);
|
|
191
|
-
this.topicStrings[TopicType.
|
|
192
|
-
TopicType.
|
|
208
|
+
this.topicStrings[TopicType.checkpoint_proposal] = createTopicString(
|
|
209
|
+
TopicType.checkpoint_proposal,
|
|
210
|
+
this.protocolVersion,
|
|
211
|
+
);
|
|
212
|
+
this.topicStrings[TopicType.checkpoint_attestation] = createTopicString(
|
|
213
|
+
TopicType.checkpoint_attestation,
|
|
193
214
|
this.protocolVersion,
|
|
194
215
|
);
|
|
195
216
|
|
|
196
|
-
// Use FishermanAttestationValidator in fisherman mode to validate attestation payloads against proposals
|
|
197
|
-
this.attestationValidator = config.fishermanMode
|
|
198
|
-
? new FishermanAttestationValidator(epochCache, mempools.attestationPool, telemetry)
|
|
199
|
-
: new AttestationValidator(epochCache);
|
|
200
217
|
this.blockProposalValidator = new BlockProposalValidator(epochCache, { txsPermitted: !config.disableTransactions });
|
|
218
|
+
this.checkpointProposalValidator = new CheckpointProposalValidator(epochCache, {
|
|
219
|
+
txsPermitted: !config.disableTransactions,
|
|
220
|
+
});
|
|
221
|
+
this.checkpointAttestationValidator = config.fishermanMode
|
|
222
|
+
? new FishermanAttestationValidator(epochCache, mempools.attestationPool, telemetry)
|
|
223
|
+
: new CheckpointAttestationValidator(epochCache);
|
|
201
224
|
|
|
202
225
|
this.gossipSubEventHandler = this.handleGossipSubEvent.bind(this);
|
|
203
226
|
|
|
204
|
-
this.blockReceivedCallback = async (block: BlockProposal): Promise<
|
|
227
|
+
this.blockReceivedCallback = async (block: BlockProposal): Promise<boolean> => {
|
|
205
228
|
this.logger.debug(
|
|
206
229
|
`Handler not yet registered: Block received callback not set. Received block for slot ${block.slotNumber} from peer.`,
|
|
207
230
|
{ p2pMessageIdentifier: await block.p2pMessageLoggingIdentifier() },
|
|
208
231
|
);
|
|
209
|
-
return
|
|
232
|
+
return false;
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
this.checkpointReceivedCallback = (
|
|
236
|
+
checkpoint: CheckpointProposalCore,
|
|
237
|
+
): Promise<CheckpointAttestation[] | undefined> => {
|
|
238
|
+
this.logger.debug(
|
|
239
|
+
`Handler not yet registered: Checkpoint received callback not set. Received checkpoint for slot ${checkpoint.slotNumber} from peer.`,
|
|
240
|
+
);
|
|
241
|
+
return Promise.resolve(undefined);
|
|
210
242
|
};
|
|
211
243
|
}
|
|
212
244
|
|
|
@@ -275,7 +307,8 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
275
307
|
|
|
276
308
|
const txTopic = createTopicString(TopicType.tx, protocolVersion);
|
|
277
309
|
const blockProposalTopic = createTopicString(TopicType.block_proposal, protocolVersion);
|
|
278
|
-
const
|
|
310
|
+
const checkpointProposalTopic = createTopicString(TopicType.checkpoint_proposal, protocolVersion);
|
|
311
|
+
const checkpointAttestationTopic = createTopicString(TopicType.checkpoint_attestation, protocolVersion);
|
|
279
312
|
|
|
280
313
|
const preferredPeersEnrs: ENR[] = config.preferredPeers.map(enr => ENR.decodeTxt(enr));
|
|
281
314
|
const directPeers = (
|
|
@@ -397,12 +430,17 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
397
430
|
invalidMessageDeliveriesWeight: -20,
|
|
398
431
|
invalidMessageDeliveriesDecay: 0.5,
|
|
399
432
|
}),
|
|
400
|
-
[
|
|
433
|
+
[blockProposalTopic]: createTopicScoreParams({
|
|
401
434
|
topicWeight: 1,
|
|
402
435
|
invalidMessageDeliveriesWeight: -20,
|
|
403
436
|
invalidMessageDeliveriesDecay: 0.5,
|
|
404
437
|
}),
|
|
405
|
-
[
|
|
438
|
+
[checkpointProposalTopic]: createTopicScoreParams({
|
|
439
|
+
topicWeight: 1,
|
|
440
|
+
invalidMessageDeliveriesWeight: -20,
|
|
441
|
+
invalidMessageDeliveriesDecay: 0.5,
|
|
442
|
+
}),
|
|
443
|
+
[checkpointAttestationTopic]: createTopicScoreParams({
|
|
406
444
|
topicWeight: 1,
|
|
407
445
|
invalidMessageDeliveriesWeight: -20,
|
|
408
446
|
invalidMessageDeliveriesDecay: 0.5,
|
|
@@ -472,17 +510,6 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
472
510
|
}
|
|
473
511
|
const announceTcpMultiaddr = convertToMultiaddr(p2pIp, p2pPort, 'tcp');
|
|
474
512
|
|
|
475
|
-
await this.peerManager.initializePeers();
|
|
476
|
-
if (!this.config.p2pDiscoveryDisabled) {
|
|
477
|
-
await this.peerDiscoveryService.start();
|
|
478
|
-
}
|
|
479
|
-
await this.node.start();
|
|
480
|
-
|
|
481
|
-
// Subscribe to standard GossipSub topics by default
|
|
482
|
-
for (const topic of getTopicsForClientAndConfig(this.clientType, this.config.disableTransactions)) {
|
|
483
|
-
this.subscribeToTopic(this.topicStrings[topic]);
|
|
484
|
-
}
|
|
485
|
-
|
|
486
513
|
// Create request response protocol handlers
|
|
487
514
|
const txHandler = reqRespTxHandler(this.mempools);
|
|
488
515
|
const goodbyeHandler = reqGoodbyeHandler(this.peerManager);
|
|
@@ -505,10 +532,32 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
505
532
|
requestResponseHandlers[ReqRespSubProtocol.TX] = txHandler.bind(this);
|
|
506
533
|
}
|
|
507
534
|
|
|
535
|
+
// Define the sub protocol validators - This is done within this start() method to gain a callback to the existing validateTx function
|
|
536
|
+
const reqrespSubProtocolValidators = {
|
|
537
|
+
...DEFAULT_SUB_PROTOCOL_VALIDATORS,
|
|
538
|
+
[ReqRespSubProtocol.TX]: this.validateRequestedTxs.bind(this),
|
|
539
|
+
[ReqRespSubProtocol.BLOCK_TXS]: this.validateRequestedBlockTxs.bind(this),
|
|
540
|
+
[ReqRespSubProtocol.BLOCK]: this.validateRequestedBlock.bind(this),
|
|
541
|
+
};
|
|
542
|
+
|
|
543
|
+
await this.peerManager.initializePeers();
|
|
544
|
+
|
|
545
|
+
await this.reqresp.start(requestResponseHandlers, reqrespSubProtocolValidators);
|
|
546
|
+
|
|
547
|
+
await this.node.start();
|
|
548
|
+
|
|
549
|
+
// Subscribe to standard GossipSub topics by default
|
|
550
|
+
for (const topic of getTopicsForClientAndConfig(this.clientType, this.config.disableTransactions)) {
|
|
551
|
+
this.subscribeToTopic(this.topicStrings[topic]);
|
|
552
|
+
}
|
|
553
|
+
|
|
508
554
|
// add GossipSub listener
|
|
509
555
|
this.node.services.pubsub.addEventListener(GossipSubEvent.MESSAGE, this.gossipSubEventHandler);
|
|
510
556
|
|
|
511
557
|
// Start running promise for peer discovery and metrics collection
|
|
558
|
+
if (!this.config.p2pDiscoveryDisabled) {
|
|
559
|
+
await this.peerDiscoveryService.start();
|
|
560
|
+
}
|
|
512
561
|
this.discoveryRunningPromise = new RunningPromise(
|
|
513
562
|
async () => {
|
|
514
563
|
await this.peerManager.heartbeat();
|
|
@@ -518,14 +567,6 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
518
567
|
);
|
|
519
568
|
this.discoveryRunningPromise.start();
|
|
520
569
|
|
|
521
|
-
// Define the sub protocol validators - This is done within this start() method to gain a callback to the existing validateTx function
|
|
522
|
-
const reqrespSubProtocolValidators = {
|
|
523
|
-
...DEFAULT_SUB_PROTOCOL_VALIDATORS,
|
|
524
|
-
[ReqRespSubProtocol.TX]: this.validateRequestedTxs.bind(this),
|
|
525
|
-
[ReqRespSubProtocol.BLOCK_TXS]: this.validateRequestedBlockTxs.bind(this),
|
|
526
|
-
[ReqRespSubProtocol.BLOCK]: this.validateRequestedBlock.bind(this),
|
|
527
|
-
};
|
|
528
|
-
await this.reqresp.start(requestResponseHandlers, reqrespSubProtocolValidators);
|
|
529
570
|
this.logger.info(`Started P2P service`, {
|
|
530
571
|
listen: this.config.listenAddress,
|
|
531
572
|
port: this.config.p2pPort,
|
|
@@ -611,6 +652,10 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
611
652
|
this.blockReceivedCallback = callback;
|
|
612
653
|
}
|
|
613
654
|
|
|
655
|
+
public registerCheckpointReceivedCallback(callback: P2PCheckpointReceivedCallback) {
|
|
656
|
+
this.checkpointReceivedCallback = callback;
|
|
657
|
+
}
|
|
658
|
+
|
|
614
659
|
/**
|
|
615
660
|
* Subscribes to a topic.
|
|
616
661
|
* @param topic - The topic to subscribe to.
|
|
@@ -656,12 +701,15 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
656
701
|
case this.topicStrings[TopicType.tx]:
|
|
657
702
|
topicType = TopicType.tx;
|
|
658
703
|
break;
|
|
659
|
-
case this.topicStrings[TopicType.block_attestation]:
|
|
660
|
-
topicType = TopicType.block_attestation;
|
|
661
|
-
break;
|
|
662
704
|
case this.topicStrings[TopicType.block_proposal]:
|
|
663
705
|
topicType = TopicType.block_proposal;
|
|
664
706
|
break;
|
|
707
|
+
case this.topicStrings[TopicType.checkpoint_proposal]:
|
|
708
|
+
topicType = TopicType.checkpoint_proposal;
|
|
709
|
+
break;
|
|
710
|
+
case this.topicStrings[TopicType.checkpoint_attestation]:
|
|
711
|
+
topicType = TopicType.checkpoint_attestation;
|
|
712
|
+
break;
|
|
665
713
|
default:
|
|
666
714
|
this.logger.error(`Received message on unknown topic: ${msg.topic}`);
|
|
667
715
|
break;
|
|
@@ -723,24 +771,28 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
723
771
|
// Determine topic type for attributes
|
|
724
772
|
if (msg.topic === this.topicStrings[TopicType.tx]) {
|
|
725
773
|
topicType = TopicType.tx;
|
|
726
|
-
} else if (msg.topic === this.topicStrings[TopicType.
|
|
727
|
-
topicType = TopicType.
|
|
774
|
+
} else if (msg.topic === this.topicStrings[TopicType.checkpoint_attestation]) {
|
|
775
|
+
topicType = TopicType.checkpoint_attestation;
|
|
728
776
|
} else if (msg.topic === this.topicStrings[TopicType.block_proposal]) {
|
|
729
777
|
topicType = TopicType.block_proposal;
|
|
778
|
+
} else if (msg.topic === this.topicStrings[TopicType.checkpoint_proposal]) {
|
|
779
|
+
topicType = TopicType.checkpoint_proposal;
|
|
730
780
|
}
|
|
731
781
|
|
|
732
782
|
// Process the message, optionally within a linked span for trace propagation
|
|
733
783
|
const processMessage = async () => {
|
|
734
784
|
if (msg.topic === this.topicStrings[TopicType.tx]) {
|
|
735
785
|
await this.handleGossipedTx(p2pMessage.payload, msgId, source);
|
|
736
|
-
}
|
|
737
|
-
if (msg.topic === this.topicStrings[TopicType.block_attestation]) {
|
|
786
|
+
} else if (msg.topic === this.topicStrings[TopicType.checkpoint_attestation]) {
|
|
738
787
|
if (this.clientType === P2PClientType.Full) {
|
|
739
|
-
await this.
|
|
788
|
+
await this.processCheckpointAttestationFromPeer(p2pMessage.payload, msgId, source);
|
|
740
789
|
}
|
|
741
|
-
}
|
|
742
|
-
if (msg.topic === this.topicStrings[TopicType.block_proposal]) {
|
|
790
|
+
} else if (msg.topic === this.topicStrings[TopicType.block_proposal]) {
|
|
743
791
|
await this.processBlockFromPeer(p2pMessage.payload, msgId, source);
|
|
792
|
+
} else if (msg.topic === this.topicStrings[TopicType.checkpoint_proposal]) {
|
|
793
|
+
await this.handleGossipedCheckpointProposal(p2pMessage.payload, msgId, source);
|
|
794
|
+
} else {
|
|
795
|
+
this.logger.error(`Received message on unknown topic: ${msg.topic}`);
|
|
744
796
|
}
|
|
745
797
|
};
|
|
746
798
|
|
|
@@ -860,27 +912,29 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
860
912
|
}
|
|
861
913
|
|
|
862
914
|
/**
|
|
863
|
-
* Process
|
|
864
|
-
*
|
|
865
|
-
*
|
|
866
|
-
* @param attestation - The attestation to process.
|
|
915
|
+
* Process a checkpoint attestation from a peer.
|
|
916
|
+
* Validates the attestation and adds it to the pool.
|
|
867
917
|
*/
|
|
868
|
-
private async
|
|
869
|
-
|
|
870
|
-
|
|
918
|
+
private async processCheckpointAttestationFromPeer(
|
|
919
|
+
payloadData: Buffer,
|
|
920
|
+
msgId: string,
|
|
921
|
+
source: PeerId,
|
|
922
|
+
): Promise<void> {
|
|
923
|
+
const validationFunc: () => Promise<ReceivedMessageValidationResult<CheckpointAttestation>> = async () => {
|
|
924
|
+
const attestation = CheckpointAttestation.fromBuffer(payloadData);
|
|
871
925
|
const pool = this.mempools.attestationPool;
|
|
872
|
-
const isValid = await this.
|
|
873
|
-
const exists = isValid && (await pool.
|
|
926
|
+
const isValid = await this.validateCheckpointAttestation(source, attestation);
|
|
927
|
+
const exists = isValid && (await pool.hasCheckpointAttestation(attestation));
|
|
874
928
|
|
|
875
929
|
let canAdd = true;
|
|
876
930
|
if (isValid && !exists) {
|
|
877
931
|
const slot = attestation.payload.header.slotNumber;
|
|
878
932
|
const { committee } = await this.epochCache.getCommittee(slot);
|
|
879
933
|
const committeeSize = committee?.length ?? 0;
|
|
880
|
-
canAdd = await pool.
|
|
934
|
+
canAdd = await pool.canAddCheckpointAttestation(attestation, committeeSize);
|
|
881
935
|
}
|
|
882
936
|
|
|
883
|
-
this.logger.trace(`Validate propagated
|
|
937
|
+
this.logger.trace(`Validate propagated checkpoint attestation`, {
|
|
884
938
|
isValid,
|
|
885
939
|
exists,
|
|
886
940
|
canAdd,
|
|
@@ -893,7 +947,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
893
947
|
} else if (exists) {
|
|
894
948
|
return { result: TopicValidatorResult.Ignore, obj: attestation };
|
|
895
949
|
} else if (!canAdd) {
|
|
896
|
-
this.logger.warn(`Dropping
|
|
950
|
+
this.logger.warn(`Dropping checkpoint attestation due to per-(slot, proposalId) attestation cap`, {
|
|
897
951
|
slot: attestation.payload.header.slotNumber.toString(),
|
|
898
952
|
archive: attestation.archive.toString(),
|
|
899
953
|
source: source.toString(),
|
|
@@ -904,11 +958,11 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
904
958
|
}
|
|
905
959
|
};
|
|
906
960
|
|
|
907
|
-
const { result, obj: attestation } = await this.validateReceivedMessage<
|
|
961
|
+
const { result, obj: attestation } = await this.validateReceivedMessage<CheckpointAttestation>(
|
|
908
962
|
validationFunc,
|
|
909
963
|
msgId,
|
|
910
964
|
source,
|
|
911
|
-
TopicType.
|
|
965
|
+
TopicType.checkpoint_attestation,
|
|
912
966
|
);
|
|
913
967
|
|
|
914
968
|
if (result !== TopicValidatorResult.Accept || !attestation) {
|
|
@@ -916,7 +970,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
916
970
|
}
|
|
917
971
|
|
|
918
972
|
this.logger.debug(
|
|
919
|
-
`Received attestation for slot ${attestation.slotNumber} from external peer ${source.toString()}`,
|
|
973
|
+
`Received checkpoint attestation for slot ${attestation.slotNumber} from external peer ${source.toString()}`,
|
|
920
974
|
{
|
|
921
975
|
p2pMessageIdentifier: await attestation.p2pMessageLoggingIdentifier(),
|
|
922
976
|
slot: attestation.slotNumber,
|
|
@@ -925,7 +979,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
925
979
|
},
|
|
926
980
|
);
|
|
927
981
|
|
|
928
|
-
await this.mempools.attestationPool.
|
|
982
|
+
await this.mempools.attestationPool.addCheckpointAttestations([attestation]);
|
|
929
983
|
}
|
|
930
984
|
|
|
931
985
|
private async processBlockFromPeer(payloadData: Buffer, msgId: string, source: PeerId): Promise<void> {
|
|
@@ -941,7 +995,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
941
995
|
isValid,
|
|
942
996
|
exists,
|
|
943
997
|
canAdd,
|
|
944
|
-
[Attributes.SLOT_NUMBER]: block.
|
|
998
|
+
[Attributes.SLOT_NUMBER]: block.slotNumber.toString(),
|
|
945
999
|
[Attributes.P2P_ID]: source.toString(),
|
|
946
1000
|
});
|
|
947
1001
|
|
|
@@ -977,6 +1031,8 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
977
1031
|
}
|
|
978
1032
|
|
|
979
1033
|
// REVIEW: callback pattern https://github.com/AztecProtocol/aztec-packages/issues/7963
|
|
1034
|
+
// REFACTOR(palla): This method should be moved to the p2p_client or to a separate component,
|
|
1035
|
+
// should not be here as it does not deal with p2p networking.
|
|
980
1036
|
@trackSpan('Libp2pService.processValidBlockProposal', async block => ({
|
|
981
1037
|
[Attributes.SLOT_NUMBER]: block.slotNumber,
|
|
982
1038
|
[Attributes.BLOCK_ARCHIVE]: block.archive.toString(),
|
|
@@ -984,17 +1040,13 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
984
1040
|
}))
|
|
985
1041
|
private async processValidBlockProposal(block: BlockProposal, sender: PeerId) {
|
|
986
1042
|
const slot = block.slotNumber;
|
|
987
|
-
const previousSlot = SlotNumber(slot - 1);
|
|
988
1043
|
this.logger.verbose(`Received block proposal for slot ${slot} from external peer ${sender.toString()}.`, {
|
|
989
1044
|
p2pMessageIdentifier: await block.p2pMessageLoggingIdentifier(),
|
|
990
|
-
slot: block.slotNumber,
|
|
991
|
-
archive: block.archive.toString(),
|
|
992
1045
|
source: sender.toString(),
|
|
1046
|
+
...block.toBlockInfo(),
|
|
993
1047
|
});
|
|
994
|
-
const attestationsForPreviousSlot = await this.mempools.attestationPool.getAttestationsForSlot(previousSlot);
|
|
995
|
-
this.logger.verbose(`Received ${attestationsForPreviousSlot.length} attestations for slot ${previousSlot}`);
|
|
996
1048
|
|
|
997
|
-
// Attempt to add proposal
|
|
1049
|
+
// Attempt to add proposal
|
|
998
1050
|
try {
|
|
999
1051
|
await this.mempools.attestationPool.addBlockProposal(block);
|
|
1000
1052
|
} catch (err: unknown) {
|
|
@@ -1009,34 +1061,125 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1009
1061
|
}
|
|
1010
1062
|
throw err;
|
|
1011
1063
|
}
|
|
1064
|
+
|
|
1065
|
+
// Mark the txs in this proposal as non-evictable
|
|
1012
1066
|
await this.mempools.txPool.markTxsAsNonEvictable(block.txHashes);
|
|
1013
|
-
const attestations = await this.blockReceivedCallback(block, sender);
|
|
1014
1067
|
|
|
1015
|
-
//
|
|
1016
|
-
//
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1068
|
+
// Call the block received callback to validate the proposal.
|
|
1069
|
+
// Note: Validators do NOT attest to individual blocks, only to checkpoint proposals.
|
|
1070
|
+
const isValid = await this.blockReceivedCallback(block, sender);
|
|
1071
|
+
if (!isValid) {
|
|
1072
|
+
this.logger.warn(`Block proposal validation failed for block ${block.blockNumber}`, block.toBlockInfo());
|
|
1073
|
+
}
|
|
1074
|
+
}
|
|
1075
|
+
|
|
1076
|
+
/**
|
|
1077
|
+
* Handle a gossiped checkpoint proposal.
|
|
1078
|
+
* Validates and processes the checkpoint proposal, then triggers the callback for attestation.
|
|
1079
|
+
*/
|
|
1080
|
+
private async handleGossipedCheckpointProposal(payloadData: Buffer, msgId: string, source: PeerId): Promise<void> {
|
|
1081
|
+
// TODO(palla/mbps): This pattern is repeated across multiple message handlers, consider abstracting it.
|
|
1082
|
+
const validationFunc: () => Promise<ReceivedMessageValidationResult<CheckpointProposal>> = async () => {
|
|
1083
|
+
const checkpoint = CheckpointProposal.fromBuffer(payloadData);
|
|
1084
|
+
const isValid = await this.validateCheckpointProposal(source, checkpoint);
|
|
1085
|
+
const pool = this.mempools.attestationPool;
|
|
1086
|
+
|
|
1087
|
+
const exists = isValid && (await pool.hasCheckpointProposal(checkpoint));
|
|
1088
|
+
const canAdd = isValid && (await pool.canAddCheckpointProposal(checkpoint));
|
|
1089
|
+
|
|
1090
|
+
this.logger.trace(`Validate propagated checkpoint proposal`, {
|
|
1091
|
+
isValid,
|
|
1092
|
+
exists,
|
|
1093
|
+
canAdd,
|
|
1094
|
+
[Attributes.SLOT_NUMBER]: checkpoint.slotNumber.toString(),
|
|
1095
|
+
[Attributes.P2P_ID]: source.toString(),
|
|
1096
|
+
});
|
|
1097
|
+
|
|
1098
|
+
if (!isValid) {
|
|
1099
|
+
return { result: TopicValidatorResult.Reject };
|
|
1100
|
+
} else if (exists) {
|
|
1101
|
+
return { result: TopicValidatorResult.Ignore, obj: checkpoint };
|
|
1102
|
+
} else if (!canAdd) {
|
|
1103
|
+
this.peerManager.penalizePeer(source, PeerErrorSeverity.MidToleranceError);
|
|
1104
|
+
this.logger.warn(`Penalizing peer for checkpoint proposal exceeding per-slot cap`, {
|
|
1105
|
+
slot: checkpoint.slotNumber.toString(),
|
|
1106
|
+
archive: checkpoint.archive.toString(),
|
|
1107
|
+
source: source.toString(),
|
|
1023
1108
|
});
|
|
1024
|
-
|
|
1109
|
+
return { result: TopicValidatorResult.Reject };
|
|
1110
|
+
} else {
|
|
1111
|
+
return { result: TopicValidatorResult.Accept, obj: checkpoint };
|
|
1025
1112
|
}
|
|
1113
|
+
};
|
|
1114
|
+
|
|
1115
|
+
const { result, obj: checkpoint } = await this.validateReceivedMessage<CheckpointProposal>(
|
|
1116
|
+
validationFunc,
|
|
1117
|
+
msgId,
|
|
1118
|
+
source,
|
|
1119
|
+
TopicType.checkpoint_proposal,
|
|
1120
|
+
);
|
|
1121
|
+
|
|
1122
|
+
if (result !== TopicValidatorResult.Accept || !checkpoint) {
|
|
1123
|
+
return;
|
|
1026
1124
|
}
|
|
1125
|
+
|
|
1126
|
+
await this.processValidCheckpointProposal(checkpoint, source);
|
|
1027
1127
|
}
|
|
1028
1128
|
|
|
1029
1129
|
/**
|
|
1030
|
-
*
|
|
1031
|
-
*
|
|
1130
|
+
* Process a validated checkpoint proposal.
|
|
1131
|
+
* Extracts and processes the last block proposal (if present) first, then processes the checkpoint.
|
|
1132
|
+
* The block callback is invoked before the checkpoint callback.
|
|
1032
1133
|
*/
|
|
1033
|
-
@trackSpan('Libp2pService.
|
|
1034
|
-
[Attributes.SLOT_NUMBER]:
|
|
1035
|
-
[Attributes.BLOCK_ARCHIVE]:
|
|
1036
|
-
[Attributes.P2P_ID]: await
|
|
1134
|
+
@trackSpan('Libp2pService.processValidCheckpointProposal', async checkpoint => ({
|
|
1135
|
+
[Attributes.SLOT_NUMBER]: checkpoint.slotNumber,
|
|
1136
|
+
[Attributes.BLOCK_ARCHIVE]: checkpoint.archive.toString(),
|
|
1137
|
+
[Attributes.P2P_ID]: await checkpoint.p2pMessageLoggingIdentifier().then(i => i.toString()),
|
|
1037
1138
|
}))
|
|
1038
|
-
private async
|
|
1039
|
-
|
|
1139
|
+
private async processValidCheckpointProposal(checkpoint: CheckpointProposal, sender: PeerId) {
|
|
1140
|
+
const slot = checkpoint.slotNumber;
|
|
1141
|
+
this.logger.verbose(`Received checkpoint proposal for slot ${slot} from external peer ${sender.toString()}.`, {
|
|
1142
|
+
p2pMessageIdentifier: await checkpoint.p2pMessageLoggingIdentifier(),
|
|
1143
|
+
slot: checkpoint.slotNumber,
|
|
1144
|
+
archive: checkpoint.archive.toString(),
|
|
1145
|
+
source: sender.toString(),
|
|
1146
|
+
});
|
|
1147
|
+
|
|
1148
|
+
// Extract block proposal before adding to pool (pool stores them separately)
|
|
1149
|
+
const blockProposal = checkpoint.getBlockProposal();
|
|
1150
|
+
|
|
1151
|
+
// Add proposal to the pool (this extracts and stores block proposal separately)
|
|
1152
|
+
await this.mempools.attestationPool.addCheckpointProposal(checkpoint);
|
|
1153
|
+
|
|
1154
|
+
// Mark txs as non-evictable if present (from the last block)
|
|
1155
|
+
if (checkpoint.txHashes.length > 0) {
|
|
1156
|
+
await this.mempools.txPool.markTxsAsNonEvictable(checkpoint.txHashes);
|
|
1157
|
+
}
|
|
1158
|
+
|
|
1159
|
+
// If there was a last block proposal, invoke the block callback first for validation.
|
|
1160
|
+
// Note: The block proposal is already stored in the pool by addCheckpointProposal.
|
|
1161
|
+
if (blockProposal) {
|
|
1162
|
+
const isValid = await this.blockReceivedCallback(blockProposal, sender);
|
|
1163
|
+
if (!isValid) {
|
|
1164
|
+
this.logger.warn(`Block proposal from checkpoint failed validation`, {
|
|
1165
|
+
slot: slot.toString(),
|
|
1166
|
+
archive: checkpoint.archive.toString(),
|
|
1167
|
+
blockNumber: blockProposal.blockNumber.toString(),
|
|
1168
|
+
});
|
|
1169
|
+
return;
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
1172
|
+
|
|
1173
|
+
// Call the checkpoint received callback with the core version (without lastBlock)
|
|
1174
|
+
// to validate and potentially generate attestations
|
|
1175
|
+
const attestations = await this.checkpointReceivedCallback(checkpoint.toCore(), sender);
|
|
1176
|
+
if (attestations && attestations.length > 0) {
|
|
1177
|
+
// If the callback returned attestations, add them to the pool and propagate them
|
|
1178
|
+
await this.mempools.attestationPool.addCheckpointAttestations(attestations);
|
|
1179
|
+
for (const attestation of attestations) {
|
|
1180
|
+
await this.propagate(attestation);
|
|
1181
|
+
}
|
|
1182
|
+
}
|
|
1040
1183
|
}
|
|
1041
1184
|
|
|
1042
1185
|
/**
|
|
@@ -1421,19 +1564,20 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1421
1564
|
}
|
|
1422
1565
|
|
|
1423
1566
|
/**
|
|
1424
|
-
* Validate
|
|
1567
|
+
* Validate a checkpoint attestation.
|
|
1425
1568
|
*
|
|
1426
|
-
* @param attestation - The attestation to validate.
|
|
1427
|
-
* @returns True if the attestation is valid, false otherwise.
|
|
1569
|
+
* @param attestation - The checkpoint attestation to validate.
|
|
1570
|
+
* @returns True if the checkpoint attestation is valid, false otherwise.
|
|
1428
1571
|
*/
|
|
1429
|
-
@trackSpan('Libp2pService.
|
|
1572
|
+
@trackSpan('Libp2pService.validateCheckpointAttestation', async (_, attestation) => ({
|
|
1430
1573
|
[Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber,
|
|
1431
1574
|
[Attributes.BLOCK_ARCHIVE]: attestation.archive.toString(),
|
|
1432
1575
|
[Attributes.P2P_ID]: await attestation.p2pMessageLoggingIdentifier().then(i => i.toString()),
|
|
1433
1576
|
}))
|
|
1434
|
-
public async
|
|
1435
|
-
const severity = await this.
|
|
1577
|
+
public async validateCheckpointAttestation(peerId: PeerId, attestation: CheckpointAttestation): Promise<boolean> {
|
|
1578
|
+
const severity = await this.checkpointAttestationValidator.validate(attestation);
|
|
1436
1579
|
if (severity) {
|
|
1580
|
+
this.logger.debug(`Penalizing peer ${peerId} for checkpoint attestation validation failure`);
|
|
1437
1581
|
this.peerManager.penalizePeer(peerId, severity);
|
|
1438
1582
|
return false;
|
|
1439
1583
|
}
|
|
@@ -1448,7 +1592,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1448
1592
|
* @returns True if the block proposal is valid, false otherwise.
|
|
1449
1593
|
*/
|
|
1450
1594
|
@trackSpan('Libp2pService.validateBlockProposal', (_peerId, block) => ({
|
|
1451
|
-
[Attributes.SLOT_NUMBER]: block.
|
|
1595
|
+
[Attributes.SLOT_NUMBER]: block.slotNumber.toString(),
|
|
1452
1596
|
}))
|
|
1453
1597
|
public async validateBlockProposal(peerId: PeerId, block: BlockProposal): Promise<boolean> {
|
|
1454
1598
|
const severity = await this.blockProposalValidator.validate(block);
|
|
@@ -1461,6 +1605,26 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1461
1605
|
return true;
|
|
1462
1606
|
}
|
|
1463
1607
|
|
|
1608
|
+
/**
|
|
1609
|
+
* Validate a checkpoint proposal.
|
|
1610
|
+
*
|
|
1611
|
+
* @param checkpoint - The checkpoint proposal to validate.
|
|
1612
|
+
* @returns True if the checkpoint proposal is valid, false otherwise.
|
|
1613
|
+
*/
|
|
1614
|
+
@trackSpan('Libp2pService.validateCheckpointProposal', (_peerId, checkpoint) => ({
|
|
1615
|
+
[Attributes.SLOT_NUMBER]: checkpoint.slotNumber.toString(),
|
|
1616
|
+
}))
|
|
1617
|
+
public async validateCheckpointProposal(peerId: PeerId, checkpoint: CheckpointProposal): Promise<boolean> {
|
|
1618
|
+
const severity = await this.checkpointProposalValidator.validate(checkpoint);
|
|
1619
|
+
if (severity) {
|
|
1620
|
+
this.logger.debug(`Penalizing peer ${peerId} for checkpoint proposal validation failure`);
|
|
1621
|
+
this.peerManager.penalizePeer(peerId, severity);
|
|
1622
|
+
return false;
|
|
1623
|
+
}
|
|
1624
|
+
|
|
1625
|
+
return true;
|
|
1626
|
+
}
|
|
1627
|
+
|
|
1464
1628
|
public getPeerScore(peerId: PeerId): number {
|
|
1465
1629
|
return this.node.services.pubsub.score.score(peerId.toString());
|
|
1466
1630
|
}
|
package/src/services/service.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { EthAddress } from '@aztec/foundation/eth-address';
|
|
2
2
|
import type { PeerInfo } from '@aztec/stdlib/interfaces/server';
|
|
3
|
-
import type {
|
|
3
|
+
import type { BlockProposal, CheckpointAttestation, CheckpointProposalCore, Gossipable } from '@aztec/stdlib/p2p';
|
|
4
4
|
import type { Tx } from '@aztec/stdlib/tx';
|
|
5
5
|
|
|
6
6
|
import type { PeerId } from '@libp2p/interface';
|
|
@@ -22,10 +22,23 @@ export enum PeerDiscoveryState {
|
|
|
22
22
|
STOPPED = 'stopped',
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
/**
|
|
26
|
+
* Callback for when a block proposal is received.
|
|
27
|
+
* Validators validate but DO NOT attest to individual blocks - attestations are only for checkpoints.
|
|
28
|
+
* @returns true if the proposal is valid, false otherwise
|
|
29
|
+
*/
|
|
30
|
+
export type P2PBlockReceivedCallback = (block: BlockProposal, sender: PeerId) => Promise<boolean>;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Callback for when a checkpoint proposal is received.
|
|
34
|
+
* The checkpoint proposal is passed as CheckpointProposalCore (without lastBlock) since
|
|
35
|
+
* the lastBlock is extracted and stored separately as a BlockProposal, and the block
|
|
36
|
+
* callback is invoked and awaited before this checkpoint callback.
|
|
37
|
+
*/
|
|
38
|
+
export type P2PCheckpointReceivedCallback = (
|
|
39
|
+
checkpoint: CheckpointProposalCore,
|
|
27
40
|
sender: PeerId,
|
|
28
|
-
) => Promise<
|
|
41
|
+
) => Promise<CheckpointAttestation[] | undefined>;
|
|
29
42
|
|
|
30
43
|
export type AuthReceivedCallback = (peerId: PeerId, authRequest: AuthRequest) => Promise<AuthResponse | undefined>;
|
|
31
44
|
|
|
@@ -70,6 +83,8 @@ export interface P2PService {
|
|
|
70
83
|
// Leaky abstraction: fix https://github.com/AztecProtocol/aztec-packages/issues/7963
|
|
71
84
|
registerBlockReceivedCallback(callback: P2PBlockReceivedCallback): void;
|
|
72
85
|
|
|
86
|
+
registerCheckpointReceivedCallback(callback: P2PCheckpointReceivedCallback): void;
|
|
87
|
+
|
|
73
88
|
getEnr(): ENR | undefined;
|
|
74
89
|
|
|
75
90
|
getPeers(includePending?: boolean): PeerInfo[];
|