@aztec/p2p 4.0.0-nightly.20260112 → 4.0.0-nightly.20260114
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/reqresp/constants.d.ts +12 -0
- package/dest/services/reqresp/constants.d.ts.map +1 -0
- package/dest/services/reqresp/constants.js +7 -0
- package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts +1 -1
- package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/block_txs/bitvector.js +7 -0
- package/dest/services/reqresp/protocols/status.d.ts +1 -1
- package/dest/services/reqresp/protocols/status.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/status.js +2 -1
- 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/reqresp/constants.ts +14 -0
- package/src/services/reqresp/protocols/block_txs/bitvector.ts +9 -0
- package/src/services/reqresp/protocols/status.ts +5 -3
- 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
package/src/client/p2p_client.ts
CHANGED
|
@@ -1,21 +1,27 @@
|
|
|
1
|
-
import { GENESIS_BLOCK_HEADER_HASH
|
|
1
|
+
import { GENESIS_BLOCK_HEADER_HASH } from '@aztec/constants';
|
|
2
2
|
import { BlockNumber, SlotNumber } from '@aztec/foundation/branded-types';
|
|
3
3
|
import { createLogger } from '@aztec/foundation/log';
|
|
4
4
|
import { DateProvider } from '@aztec/foundation/timer';
|
|
5
|
-
import type { AztecAsyncKVStore,
|
|
5
|
+
import type { AztecAsyncKVStore, AztecAsyncSingleton } from '@aztec/kv-store';
|
|
6
|
+
import { L2TipsKVStore } from '@aztec/kv-store/stores';
|
|
6
7
|
import {
|
|
7
8
|
type EthAddress,
|
|
8
|
-
type L2BlockId,
|
|
9
9
|
type L2BlockNew,
|
|
10
10
|
type L2BlockSource,
|
|
11
11
|
L2BlockStream,
|
|
12
12
|
type L2BlockStreamEvent,
|
|
13
13
|
type L2Tips,
|
|
14
|
+
type L2TipsStore,
|
|
14
15
|
} from '@aztec/stdlib/block';
|
|
15
16
|
import type { ContractDataSource } from '@aztec/stdlib/contract';
|
|
16
17
|
import { getTimestampForSlot } from '@aztec/stdlib/epoch-helpers';
|
|
17
18
|
import { type PeerInfo, tryStop } from '@aztec/stdlib/interfaces/server';
|
|
18
|
-
import {
|
|
19
|
+
import {
|
|
20
|
+
type BlockProposal,
|
|
21
|
+
CheckpointAttestation,
|
|
22
|
+
type CheckpointProposal,
|
|
23
|
+
type P2PClientType,
|
|
24
|
+
} from '@aztec/stdlib/p2p';
|
|
19
25
|
import type { Tx, TxHash } from '@aztec/stdlib/tx';
|
|
20
26
|
import { Attributes, type TelemetryClient, WithTracer, getTelemetryClient, trackSpan } from '@aztec/telemetry-client';
|
|
21
27
|
|
|
@@ -33,7 +39,7 @@ import {
|
|
|
33
39
|
type ReqRespSubProtocolValidators,
|
|
34
40
|
} from '../services/reqresp/interface.js';
|
|
35
41
|
import { chunkTxHashesRequest } from '../services/reqresp/protocols/tx.js';
|
|
36
|
-
import type { P2PBlockReceivedCallback, P2PService } from '../services/service.js';
|
|
42
|
+
import type { P2PBlockReceivedCallback, P2PCheckpointReceivedCallback, P2PService } from '../services/service.js';
|
|
37
43
|
import { TxCollection } from '../services/tx_collection/tx_collection.js';
|
|
38
44
|
import { TxProvider } from '../services/tx_provider.js';
|
|
39
45
|
import { type P2P, P2PClientState, type P2PSyncState } from './interface.js';
|
|
@@ -55,10 +61,7 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
|
|
|
55
61
|
private provenBlockNumberAtStart = -1;
|
|
56
62
|
private finalizedBlockNumberAtStart = -1;
|
|
57
63
|
|
|
58
|
-
private
|
|
59
|
-
private synchedLatestBlockNumber: AztecAsyncSingleton<BlockNumber>;
|
|
60
|
-
private synchedProvenBlockNumber: AztecAsyncSingleton<BlockNumber>;
|
|
61
|
-
private synchedFinalizedBlockNumber: AztecAsyncSingleton<BlockNumber>;
|
|
64
|
+
private l2Tips: L2TipsStore;
|
|
62
65
|
private synchedLatestSlot: AztecAsyncSingleton<bigint>;
|
|
63
66
|
|
|
64
67
|
private txPool: TxPool;
|
|
@@ -107,7 +110,8 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
|
|
|
107
110
|
);
|
|
108
111
|
|
|
109
112
|
// Default to collecting all txs when we see a valid proposal
|
|
110
|
-
// This can be overridden by the validator client to
|
|
113
|
+
// This can be overridden by the validator client to validate, and it will call getTxsForBlockProposal on its own
|
|
114
|
+
// Note: Validators do NOT attest to individual blocks - attestations are only for checkpoint proposals.
|
|
111
115
|
// TODO(palla/txs): We should not trigger a request for txs on a proposal before fully validating it. We need to bring
|
|
112
116
|
// validator-client code into here so we can validate a proposal is reasonable.
|
|
113
117
|
this.registerBlockProposalHandler(async (block, sender) => {
|
|
@@ -116,21 +120,17 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
|
|
|
116
120
|
const constants = this.txCollection.getConstants();
|
|
117
121
|
const nextSlotTimestampSeconds = Number(getTimestampForSlot(SlotNumber(block.slotNumber + 1), constants));
|
|
118
122
|
const deadline = new Date(nextSlotTimestampSeconds * 1000);
|
|
119
|
-
const parentBlock = await this.l2BlockSource.getBlockHeaderByArchive(block.
|
|
123
|
+
const parentBlock = await this.l2BlockSource.getBlockHeaderByArchive(block.blockHeader.lastArchive.root);
|
|
120
124
|
if (!parentBlock) {
|
|
121
125
|
this.log.debug(`Cannot collect txs for proposal as parent block not found`);
|
|
122
|
-
return;
|
|
126
|
+
return false;
|
|
123
127
|
}
|
|
124
128
|
const blockNumber = BlockNumber(parentBlock.getBlockNumber() + 1);
|
|
125
129
|
await this.txProvider.getTxsForBlockProposal(block, blockNumber, { pinnedPeer: sender, deadline });
|
|
126
|
-
return
|
|
130
|
+
return true;
|
|
127
131
|
});
|
|
128
132
|
|
|
129
|
-
|
|
130
|
-
this.synchedBlockHashes = store.openMap('p2p_pool_block_hashes');
|
|
131
|
-
this.synchedLatestBlockNumber = store.openSingleton('p2p_pool_last_l2_block');
|
|
132
|
-
this.synchedProvenBlockNumber = store.openSingleton('p2p_pool_last_proven_l2_block');
|
|
133
|
-
this.synchedFinalizedBlockNumber = store.openSingleton('p2p_pool_last_finalized_l2_block');
|
|
133
|
+
this.l2Tips = new L2TipsKVStore(store, 'p2p_client');
|
|
134
134
|
this.synchedLatestSlot = store.openSingleton('p2p_pool_last_l2_slot');
|
|
135
135
|
}
|
|
136
136
|
|
|
@@ -156,7 +156,7 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
|
|
|
156
156
|
}
|
|
157
157
|
|
|
158
158
|
public getL2BlockHash(number: BlockNumber): Promise<string | undefined> {
|
|
159
|
-
return this.
|
|
159
|
+
return this.l2Tips.getL2BlockHash(number);
|
|
160
160
|
}
|
|
161
161
|
|
|
162
162
|
public updateP2PConfig(config: Partial<P2PConfig>): Promise<void> {
|
|
@@ -165,56 +165,20 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
|
|
|
165
165
|
return Promise.resolve();
|
|
166
166
|
}
|
|
167
167
|
|
|
168
|
-
public
|
|
169
|
-
|
|
170
|
-
let latestBlockHash: string | undefined;
|
|
171
|
-
|
|
172
|
-
const provenBlockNumber = await this.getSyncedProvenBlockNum();
|
|
173
|
-
let provenBlockHash: string | undefined;
|
|
174
|
-
|
|
175
|
-
const finalizedBlockNumber = await this.getSyncedFinalizedBlockNum();
|
|
176
|
-
let finalizedBlockHash: string | undefined;
|
|
177
|
-
|
|
178
|
-
if (latestBlockNumber > 0) {
|
|
179
|
-
latestBlockHash = await this.synchedBlockHashes.getAsync(latestBlockNumber);
|
|
180
|
-
if (typeof latestBlockHash === 'undefined') {
|
|
181
|
-
throw new Error(`Block hash for latest block ${latestBlockNumber} not found in p2p client`);
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
if (provenBlockNumber > 0) {
|
|
186
|
-
provenBlockHash = await this.synchedBlockHashes.getAsync(provenBlockNumber);
|
|
187
|
-
if (typeof provenBlockHash === 'undefined') {
|
|
188
|
-
throw new Error(`Block hash for proven block ${provenBlockNumber} not found in p2p client`);
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
if (finalizedBlockNumber > 0) {
|
|
193
|
-
finalizedBlockHash = await this.synchedBlockHashes.getAsync(finalizedBlockNumber);
|
|
194
|
-
if (typeof finalizedBlockHash === 'undefined') {
|
|
195
|
-
throw new Error(`Block hash for finalized block ${finalizedBlockNumber} not found in p2p client`);
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
const genesisHash = GENESIS_BLOCK_HEADER_HASH.toString();
|
|
200
|
-
|
|
201
|
-
return {
|
|
202
|
-
latest: { hash: latestBlockHash ?? genesisHash, number: latestBlockNumber },
|
|
203
|
-
proven: { hash: provenBlockHash ?? genesisHash, number: provenBlockNumber },
|
|
204
|
-
finalized: { hash: finalizedBlockHash ?? genesisHash, number: finalizedBlockNumber },
|
|
205
|
-
};
|
|
168
|
+
public getL2Tips(): Promise<L2Tips> {
|
|
169
|
+
return this.l2Tips.getL2Tips();
|
|
206
170
|
}
|
|
207
171
|
|
|
208
172
|
public async handleBlockStreamEvent(event: L2BlockStreamEvent): Promise<void> {
|
|
209
173
|
this.log.debug(`Handling block stream event ${event.type}`);
|
|
174
|
+
|
|
210
175
|
switch (event.type) {
|
|
211
176
|
case 'blocks-added':
|
|
212
|
-
await this.handleLatestL2Blocks(event.blocks
|
|
177
|
+
await this.handleLatestL2Blocks(event.blocks);
|
|
213
178
|
break;
|
|
214
179
|
case 'chain-finalized': {
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
const from = BlockNumber((await this.getSyncedFinalizedBlockNum()) + 1);
|
|
180
|
+
const oldFinalizedBlockNum = await this.getSyncedFinalizedBlockNum();
|
|
181
|
+
const from = BlockNumber(oldFinalizedBlockNum + 1);
|
|
218
182
|
const limit = event.block.number - from + 1;
|
|
219
183
|
if (limit > 0) {
|
|
220
184
|
const oldBlocks = await this.l2BlockSource.getBlocks(from, limit);
|
|
@@ -222,28 +186,24 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
|
|
|
222
186
|
}
|
|
223
187
|
break;
|
|
224
188
|
}
|
|
225
|
-
case 'chain-proven':
|
|
226
|
-
await this.setBlockHash(event.block);
|
|
189
|
+
case 'chain-proven':
|
|
227
190
|
this.txCollection.stopCollectingForBlocksUpTo(event.block.number);
|
|
228
|
-
await this.synchedProvenBlockNumber.set(event.block.number);
|
|
229
191
|
break;
|
|
230
|
-
}
|
|
231
192
|
case 'chain-pruned':
|
|
232
|
-
await this.setBlockHash(event.block);
|
|
233
193
|
this.txCollection.stopCollectingForBlocksAfter(event.block.number);
|
|
234
194
|
await this.handlePruneL2Blocks(event.block.number);
|
|
235
195
|
break;
|
|
196
|
+
case 'chain-checkpointed':
|
|
197
|
+
break;
|
|
236
198
|
default: {
|
|
237
199
|
const _: never = event;
|
|
238
200
|
break;
|
|
239
201
|
}
|
|
240
202
|
}
|
|
241
|
-
}
|
|
242
203
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
}
|
|
204
|
+
// Pass the event through to our l2 tips store
|
|
205
|
+
await this.l2Tips.handleBlockStreamEvent(event);
|
|
206
|
+
await this.startServiceIfSynched();
|
|
247
207
|
}
|
|
248
208
|
|
|
249
209
|
#assertIsReady() {
|
|
@@ -267,9 +227,9 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
|
|
|
267
227
|
|
|
268
228
|
// get the current latest block numbers
|
|
269
229
|
const latestBlockNumbers = await this.l2BlockSource.getL2Tips();
|
|
270
|
-
this.latestBlockNumberAtStart = latestBlockNumbers.
|
|
271
|
-
this.provenBlockNumberAtStart = latestBlockNumbers.proven.number;
|
|
272
|
-
this.finalizedBlockNumberAtStart = latestBlockNumbers.finalized.number;
|
|
230
|
+
this.latestBlockNumberAtStart = latestBlockNumbers.proposed.number;
|
|
231
|
+
this.provenBlockNumberAtStart = latestBlockNumbers.proven.block.number;
|
|
232
|
+
this.finalizedBlockNumberAtStart = latestBlockNumbers.finalized.block.number;
|
|
273
233
|
|
|
274
234
|
const syncedLatestBlock = (await this.getSyncedLatestBlockNum()) + 1;
|
|
275
235
|
const syncedProvenBlock = (await this.getSyncedProvenBlockNum()) + 1;
|
|
@@ -371,23 +331,32 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
|
|
|
371
331
|
return this.p2pService.propagate(proposal);
|
|
372
332
|
}
|
|
373
333
|
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
334
|
+
@trackSpan('p2pClient.broadcastCheckpointProposal', async proposal => ({
|
|
335
|
+
[Attributes.SLOT_NUMBER]: proposal.slotNumber,
|
|
336
|
+
[Attributes.BLOCK_ARCHIVE]: proposal.archive.toString(),
|
|
337
|
+
[Attributes.P2P_ID]: (await proposal.p2pMessageLoggingIdentifier()).toString(),
|
|
338
|
+
}))
|
|
339
|
+
public broadcastCheckpointProposal(proposal: CheckpointProposal): Promise<void> {
|
|
340
|
+
this.log.verbose(`Broadcasting checkpoint proposal for slot ${proposal.slotNumber} to peers`);
|
|
341
|
+
return this.p2pService.propagate(proposal);
|
|
377
342
|
}
|
|
378
343
|
|
|
379
|
-
public async
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
: this.attestationPool.getAttestationsForSlot(slot));
|
|
344
|
+
public async broadcastCheckpointAttestations(attestations: CheckpointAttestation[]): Promise<void> {
|
|
345
|
+
this.log.verbose(`Broadcasting ${attestations.length} checkpoint attestations to peers`);
|
|
346
|
+
await Promise.all(attestations.map(att => this.p2pService.propagate(att)));
|
|
383
347
|
}
|
|
384
348
|
|
|
385
|
-
public
|
|
386
|
-
|
|
349
|
+
public async getCheckpointAttestationsForSlot(
|
|
350
|
+
slot: SlotNumber,
|
|
351
|
+
proposalId?: string,
|
|
352
|
+
): Promise<CheckpointAttestation[]> {
|
|
353
|
+
return await (proposalId
|
|
354
|
+
? this.attestationPool.getCheckpointAttestationsForSlotAndProposal(slot, proposalId)
|
|
355
|
+
: this.attestationPool.getCheckpointAttestationsForSlot(slot));
|
|
387
356
|
}
|
|
388
357
|
|
|
389
|
-
public
|
|
390
|
-
return this.attestationPool.
|
|
358
|
+
public addCheckpointAttestations(attestations: CheckpointAttestation[]): Promise<void> {
|
|
359
|
+
return this.attestationPool.addCheckpointAttestations(attestations);
|
|
391
360
|
}
|
|
392
361
|
|
|
393
362
|
// REVIEW: https://github.com/AztecProtocol/aztec-packages/issues/7963
|
|
@@ -396,6 +365,10 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
|
|
|
396
365
|
this.p2pService.registerBlockReceivedCallback(handler);
|
|
397
366
|
}
|
|
398
367
|
|
|
368
|
+
public registerCheckpointProposalHandler(handler: P2PCheckpointReceivedCallback): void {
|
|
369
|
+
this.p2pService.registerCheckpointReceivedCallback(handler);
|
|
370
|
+
}
|
|
371
|
+
|
|
399
372
|
/**
|
|
400
373
|
* Uses the batched Request Response protocol to request a set of transactions from the network.
|
|
401
374
|
*/
|
|
@@ -638,7 +611,8 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
|
|
|
638
611
|
* @returns Block number of latest L2 Block we've synced with.
|
|
639
612
|
*/
|
|
640
613
|
public async getSyncedLatestBlockNum(): Promise<BlockNumber> {
|
|
641
|
-
|
|
614
|
+
const tips = await this.l2Tips.getL2Tips();
|
|
615
|
+
return tips.proposed.number;
|
|
642
616
|
}
|
|
643
617
|
|
|
644
618
|
/**
|
|
@@ -646,11 +620,13 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
|
|
|
646
620
|
* @returns Block number of latest proven L2 Block we've synced with.
|
|
647
621
|
*/
|
|
648
622
|
public async getSyncedProvenBlockNum(): Promise<BlockNumber> {
|
|
649
|
-
|
|
623
|
+
const tips = await this.l2Tips.getL2Tips();
|
|
624
|
+
return tips.proven.block.number;
|
|
650
625
|
}
|
|
651
626
|
|
|
652
627
|
public async getSyncedFinalizedBlockNum(): Promise<BlockNumber> {
|
|
653
|
-
|
|
628
|
+
const tips = await this.l2Tips.getL2Tips();
|
|
629
|
+
return tips.finalized.block.number;
|
|
654
630
|
}
|
|
655
631
|
|
|
656
632
|
/** Returns latest L2 slot for which we have seen an L2 block. */
|
|
@@ -705,20 +681,8 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
|
|
|
705
681
|
await this.startCollectingMissingTxs(blocks);
|
|
706
682
|
|
|
707
683
|
const lastBlock = blocks.at(-1)!;
|
|
708
|
-
|
|
709
|
-
await Promise.all(
|
|
710
|
-
blocks.map(async block =>
|
|
711
|
-
this.setBlockHash({
|
|
712
|
-
number: block.number,
|
|
713
|
-
hash: await block.hash().then(h => h.toString()),
|
|
714
|
-
}),
|
|
715
|
-
),
|
|
716
|
-
);
|
|
717
|
-
|
|
718
|
-
await this.synchedLatestBlockNumber.set(lastBlock.number);
|
|
719
684
|
await this.synchedLatestSlot.set(BigInt(lastBlock.header.getSlot()));
|
|
720
685
|
this.log.verbose(`Synched to latest block ${lastBlock.number}`);
|
|
721
|
-
await this.startServiceIfSynched();
|
|
722
686
|
}
|
|
723
687
|
|
|
724
688
|
/** Request txs for unproven blocks so the prover node has more chances to get them. */
|
|
@@ -769,12 +733,9 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
|
|
|
769
733
|
await this.txPool.deleteTxs(txHashes, { permanently: true });
|
|
770
734
|
await this.txPool.cleanupDeletedMinedTxs(lastBlockNum);
|
|
771
735
|
|
|
772
|
-
await this.attestationPool.
|
|
736
|
+
await this.attestationPool.deleteCheckpointAttestationsOlderThan(lastBlockSlot);
|
|
773
737
|
|
|
774
|
-
await this.synchedFinalizedBlockNumber.set(lastBlockNum);
|
|
775
738
|
this.log.debug(`Synched to finalized block ${lastBlockNum} at slot ${lastBlockSlot}`);
|
|
776
|
-
|
|
777
|
-
await this.startServiceIfSynched();
|
|
778
739
|
}
|
|
779
740
|
|
|
780
741
|
/**
|
|
@@ -822,18 +783,16 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
|
|
|
822
783
|
} else {
|
|
823
784
|
await this.txPool.markMinedAsPending(minedTxsFromReorg, latestBlock);
|
|
824
785
|
}
|
|
825
|
-
|
|
826
|
-
await this.synchedLatestBlockNumber.set(latestBlock);
|
|
827
|
-
// no need to update block hashes, as they will be updated as new blocks are added
|
|
828
786
|
}
|
|
829
787
|
|
|
830
788
|
private async startServiceIfSynched() {
|
|
831
789
|
if (this.currentState !== P2PClientState.SYNCHING) {
|
|
832
790
|
return;
|
|
833
791
|
}
|
|
834
|
-
const
|
|
835
|
-
const
|
|
836
|
-
const
|
|
792
|
+
const tips = await this.l2Tips.getL2Tips();
|
|
793
|
+
const syncedFinalizedBlock = tips.finalized.block.number;
|
|
794
|
+
const syncedProvenBlock = tips.proven.block.number;
|
|
795
|
+
const syncedLatestBlock = tips.proposed.number;
|
|
837
796
|
|
|
838
797
|
if (
|
|
839
798
|
syncedLatestBlock >= this.latestBlockNumberAtStart &&
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import type { SlotNumber } from '@aztec/foundation/branded-types';
|
|
2
|
-
import type {
|
|
2
|
+
import type {
|
|
3
|
+
BlockProposal,
|
|
4
|
+
CheckpointAttestation,
|
|
5
|
+
CheckpointProposal,
|
|
6
|
+
CheckpointProposalCore,
|
|
7
|
+
} from '@aztec/stdlib/p2p';
|
|
3
8
|
|
|
4
9
|
/**
|
|
5
10
|
* An Attestation Pool contains attestations collected by a validator
|
|
@@ -32,75 +37,74 @@ export interface AttestationPool {
|
|
|
32
37
|
hasBlockProposal(idOrProposal: string | BlockProposal): Promise<boolean>;
|
|
33
38
|
|
|
34
39
|
/**
|
|
35
|
-
*
|
|
40
|
+
* Adds a checkpoint proposal to the pool.
|
|
36
41
|
*
|
|
37
|
-
*
|
|
42
|
+
* If the proposal contains a lastBlock, the BlockProposal is automatically extracted
|
|
43
|
+
* and stored separately via addBlockProposal. The checkpoint proposal is then stored
|
|
44
|
+
* without the lastBlock info (as CheckpointProposalCore).
|
|
45
|
+
*
|
|
46
|
+
* @param proposal - The checkpoint proposal to add
|
|
47
|
+
* @throws ProposalSlotCapExceededError if the slot has reached the maximum number of proposals
|
|
38
48
|
*/
|
|
39
|
-
|
|
49
|
+
addCheckpointProposal(proposal: CheckpointProposal): Promise<void>;
|
|
40
50
|
|
|
41
51
|
/**
|
|
42
|
-
*
|
|
52
|
+
* Get checkpoint proposal by its ID.
|
|
53
|
+
*
|
|
54
|
+
* Returns a CheckpointProposalCore (without lastBlock info) since the lastBlock
|
|
55
|
+
* is extracted and stored separately as a BlockProposal when added.
|
|
43
56
|
*
|
|
44
|
-
* @param
|
|
57
|
+
* @param id - The ID of the checkpoint proposal to retrieve (proposal.archive)
|
|
58
|
+
* @return The checkpoint proposal core if it exists, otherwise undefined.
|
|
45
59
|
*/
|
|
46
|
-
|
|
60
|
+
getCheckpointProposal(id: string): Promise<CheckpointProposalCore | undefined>;
|
|
47
61
|
|
|
48
62
|
/**
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
* Removes all attestations associated with a slot
|
|
63
|
+
* Check if a checkpoint proposal exists in the pool
|
|
52
64
|
*
|
|
53
|
-
* @param
|
|
65
|
+
* @param idOrProposal - The ID of the checkpoint proposal or the proposal itself
|
|
66
|
+
* @return True if the proposal exists, false otherwise.
|
|
54
67
|
*/
|
|
55
|
-
|
|
68
|
+
hasCheckpointProposal(idOrProposal: string | CheckpointProposal): Promise<boolean>;
|
|
56
69
|
|
|
57
70
|
/**
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
* Removes all attestations associated with a slot
|
|
71
|
+
* Add checkpoint attestations to the pool
|
|
61
72
|
*
|
|
62
|
-
* @param
|
|
73
|
+
* @param attestations - Checkpoint attestations to add into the pool
|
|
63
74
|
*/
|
|
64
|
-
|
|
75
|
+
addCheckpointAttestations(attestations: CheckpointAttestation[]): Promise<void>;
|
|
65
76
|
|
|
66
77
|
/**
|
|
67
|
-
* Delete
|
|
68
|
-
*
|
|
69
|
-
* Removes all attestations associated with a slot and proposal
|
|
78
|
+
* Delete checkpoint attestations older than the given slot
|
|
70
79
|
*
|
|
71
|
-
* @param slot - The slot to
|
|
72
|
-
* @param proposalId - The proposal to delete.
|
|
80
|
+
* @param slot - The oldest slot to keep.
|
|
73
81
|
*/
|
|
74
|
-
|
|
82
|
+
deleteCheckpointAttestationsOlderThan(slot: SlotNumber): Promise<void>;
|
|
75
83
|
|
|
76
84
|
/**
|
|
77
|
-
* Get all
|
|
78
|
-
*
|
|
79
|
-
* Retrieve all of the attestations observed pertaining to a given slot
|
|
85
|
+
* Get all checkpoint attestations for a given slot
|
|
80
86
|
*
|
|
81
87
|
* @param slot - The slot to query
|
|
82
|
-
* @return
|
|
88
|
+
* @return CheckpointAttestations
|
|
83
89
|
*/
|
|
84
|
-
|
|
90
|
+
getCheckpointAttestationsForSlot(slot: SlotNumber): Promise<CheckpointAttestation[]>;
|
|
85
91
|
|
|
86
92
|
/**
|
|
87
|
-
* Get
|
|
88
|
-
*
|
|
89
|
-
* Retrieve all of the attestations observed pertaining to a given slot
|
|
93
|
+
* Get checkpoint attestations for slot and given proposal
|
|
90
94
|
*
|
|
91
95
|
* @param slot - The slot to query
|
|
92
96
|
* @param proposalId - The proposal to query
|
|
93
|
-
* @return
|
|
97
|
+
* @return CheckpointAttestations
|
|
94
98
|
*/
|
|
95
|
-
|
|
99
|
+
getCheckpointAttestationsForSlotAndProposal(slot: SlotNumber, proposalId: string): Promise<CheckpointAttestation[]>;
|
|
96
100
|
|
|
97
101
|
/**
|
|
98
|
-
* Check if a specific attestation exists in the pool
|
|
102
|
+
* Check if a specific checkpoint attestation exists in the pool
|
|
99
103
|
*
|
|
100
104
|
* @param attestation - The attestation to check
|
|
101
105
|
* @return True if the attestation exists, false otherwise
|
|
102
106
|
*/
|
|
103
|
-
|
|
107
|
+
hasCheckpointAttestation(attestation: CheckpointAttestation): Promise<boolean>;
|
|
104
108
|
|
|
105
109
|
/**
|
|
106
110
|
* Returns whether adding this proposal is permitted at current capacity:
|
|
@@ -114,16 +118,39 @@ export interface AttestationPool {
|
|
|
114
118
|
canAddProposal(block: BlockProposal): Promise<boolean>;
|
|
115
119
|
|
|
116
120
|
/**
|
|
117
|
-
* Returns whether
|
|
118
|
-
*
|
|
119
|
-
*
|
|
120
|
-
*
|
|
121
|
+
* Returns whether adding this checkpoint proposal is permitted at current capacity.
|
|
122
|
+
*
|
|
123
|
+
* @param proposal - The checkpoint proposal to check
|
|
124
|
+
* @returns True if the proposal can be added, false otherwise.
|
|
125
|
+
*/
|
|
126
|
+
canAddCheckpointProposal(proposal: CheckpointProposal): Promise<boolean>;
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Returns whether a checkpoint attestation would be accepted for (slot, proposalId).
|
|
121
130
|
*
|
|
122
131
|
* @param attestation - The attestation to check
|
|
123
|
-
* @param committeeSize - Committee size for the attestation's slot
|
|
132
|
+
* @param committeeSize - Committee size for the attestation's slot
|
|
124
133
|
* @returns True if the attestation can be added, false otherwise.
|
|
125
134
|
*/
|
|
126
|
-
|
|
135
|
+
canAddCheckpointAttestation(attestation: CheckpointAttestation, committeeSize: number): Promise<boolean>;
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Returns whether the checkpoint proposal cap for the given slot has been reached.
|
|
139
|
+
*
|
|
140
|
+
* @param slot - The slot to check
|
|
141
|
+
* @returns True if the cap has been reached, false otherwise.
|
|
142
|
+
*/
|
|
143
|
+
hasReachedCheckpointProposalCap(slot: SlotNumber): Promise<boolean>;
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Returns whether the checkpoint attestation cap for the given slot and proposal has been reached.
|
|
147
|
+
*
|
|
148
|
+
* @param slot - The slot to check
|
|
149
|
+
* @param proposalId - The proposal to check
|
|
150
|
+
* @param committeeSize - Committee size for the slot
|
|
151
|
+
* @returns True if the cap has been reached, false otherwise.
|
|
152
|
+
*/
|
|
153
|
+
hasReachedCheckpointAttestationCap(slot: SlotNumber, proposalId: string, committeeSize: number): Promise<boolean>;
|
|
127
154
|
|
|
128
155
|
/** Returns whether the pool is empty. */
|
|
129
156
|
isEmpty(): Promise<boolean>;
|