@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.
Files changed (86) hide show
  1. package/dest/client/interface.d.ts +18 -5
  2. package/dest/client/interface.d.ts.map +1 -1
  3. package/dest/client/p2p_client.d.ts +9 -12
  4. package/dest/client/p2p_client.d.ts.map +1 -1
  5. package/dest/client/p2p_client.js +59 -103
  6. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +61 -42
  7. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
  8. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts +1 -1
  9. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts.map +1 -1
  10. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.js +225 -262
  11. package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts +21 -18
  12. package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts.map +1 -1
  13. package/dest/mem_pools/attestation_pool/kv_attestation_pool.js +113 -108
  14. package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts +17 -16
  15. package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts.map +1 -1
  16. package/dest/mem_pools/attestation_pool/memory_attestation_pool.js +89 -128
  17. package/dest/mem_pools/attestation_pool/mocks.d.ts +7 -6
  18. package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -1
  19. package/dest/mem_pools/attestation_pool/mocks.js +9 -8
  20. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +4 -4
  21. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -1
  22. package/dest/msg_validators/attestation_validator/attestation_validator.js +12 -10
  23. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts +5 -5
  24. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts.map +1 -1
  25. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.js +5 -5
  26. package/dest/msg_validators/index.d.ts +2 -2
  27. package/dest/msg_validators/index.d.ts.map +1 -1
  28. package/dest/msg_validators/index.js +1 -1
  29. package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts +9 -0
  30. package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts.map +1 -0
  31. package/dest/msg_validators/proposal_validator/block_proposal_validator.js +6 -0
  32. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts +9 -0
  33. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts.map +1 -0
  34. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.js +6 -0
  35. package/dest/msg_validators/proposal_validator/index.d.ts +4 -0
  36. package/dest/msg_validators/proposal_validator/index.d.ts.map +1 -0
  37. package/dest/msg_validators/proposal_validator/index.js +3 -0
  38. package/dest/msg_validators/proposal_validator/proposal_validator.d.ts +13 -0
  39. package/dest/msg_validators/proposal_validator/proposal_validator.d.ts.map +1 -0
  40. package/dest/msg_validators/{block_proposal_validator/block_proposal_validator.js → proposal_validator/proposal_validator.js} +19 -21
  41. package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.d.ts +23 -0
  42. package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.d.ts.map +1 -0
  43. package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.js +183 -0
  44. package/dest/services/dummy_service.d.ts +6 -2
  45. package/dest/services/dummy_service.d.ts.map +1 -1
  46. package/dest/services/dummy_service.js +3 -0
  47. package/dest/services/encoding.d.ts +1 -1
  48. package/dest/services/encoding.d.ts.map +1 -1
  49. package/dest/services/encoding.js +4 -2
  50. package/dest/services/libp2p/libp2p_service.d.ts +26 -10
  51. package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
  52. package/dest/services/libp2p/libp2p_service.js +218 -88
  53. package/dest/services/service.d.ts +16 -3
  54. package/dest/services/service.d.ts.map +1 -1
  55. package/dest/testbench/p2p_client_testbench_worker.js +25 -11
  56. package/dest/testbench/worker_client_manager.d.ts +1 -1
  57. package/dest/testbench/worker_client_manager.d.ts.map +1 -1
  58. package/dest/testbench/worker_client_manager.js +6 -1
  59. package/package.json +14 -14
  60. package/src/client/interface.ts +19 -4
  61. package/src/client/p2p_client.ts +69 -110
  62. package/src/mem_pools/attestation_pool/attestation_pool.ts +68 -41
  63. package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +231 -287
  64. package/src/mem_pools/attestation_pool/kv_attestation_pool.ts +162 -140
  65. package/src/mem_pools/attestation_pool/memory_attestation_pool.ts +141 -164
  66. package/src/mem_pools/attestation_pool/mocks.ts +13 -9
  67. package/src/msg_validators/attestation_validator/attestation_validator.ts +16 -13
  68. package/src/msg_validators/attestation_validator/fisherman_attestation_validator.ts +7 -7
  69. package/src/msg_validators/index.ts +1 -1
  70. package/src/msg_validators/proposal_validator/block_proposal_validator.ts +10 -0
  71. package/src/msg_validators/proposal_validator/checkpoint_proposal_validator.ts +13 -0
  72. package/src/msg_validators/proposal_validator/index.ts +3 -0
  73. package/src/msg_validators/{block_proposal_validator/block_proposal_validator.ts → proposal_validator/proposal_validator.ts} +23 -28
  74. package/src/msg_validators/proposal_validator/proposal_validator_test_suite.ts +206 -0
  75. package/src/services/dummy_service.ts +6 -0
  76. package/src/services/encoding.ts +3 -1
  77. package/src/services/libp2p/libp2p_service.ts +258 -94
  78. package/src/services/service.ts +19 -4
  79. package/src/testbench/p2p_client_testbench_worker.ts +34 -11
  80. package/src/testbench/worker_client_manager.ts +6 -1
  81. package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts +0 -12
  82. package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts.map +0 -1
  83. package/dest/msg_validators/block_proposal_validator/index.d.ts +0 -2
  84. package/dest/msg_validators/block_proposal_validator/index.d.ts.map +0 -1
  85. package/dest/msg_validators/block_proposal_validator/index.js +0 -1
  86. package/src/msg_validators/block_proposal_validator/index.ts +0 -1
@@ -3,7 +3,12 @@ import { Fr } from '@aztec/foundation/curves/bn254';
3
3
  import { toArray } from '@aztec/foundation/iterable';
4
4
  import { createLogger } from '@aztec/foundation/log';
5
5
  import type { AztecAsyncKVStore, AztecAsyncMap, AztecAsyncMultiMap } from '@aztec/kv-store';
6
- import { BlockAttestation, BlockProposal } from '@aztec/stdlib/p2p';
6
+ import {
7
+ BlockProposal,
8
+ CheckpointAttestation,
9
+ CheckpointProposal,
10
+ type CheckpointProposalCore,
11
+ } from '@aztec/stdlib/p2p';
7
12
  import { type TelemetryClient, getTelemetryClient } from '@aztec/telemetry-client';
8
13
 
9
14
  import { ProposalSlotCapExceededError } from '../../errors/attestation-pool.error.js';
@@ -14,37 +19,46 @@ export const MAX_PROPOSALS_PER_SLOT = 5;
14
19
  export const ATTESTATION_CAP_BUFFER = 10;
15
20
 
16
21
  export class KvAttestationPool implements AttestationPool {
17
- private metrics: PoolInstrumentation<BlockAttestation>;
22
+ private metrics: PoolInstrumentation<CheckpointAttestation>;
18
23
 
19
- private attestations: AztecAsyncMap<string, Buffer>;
20
24
  private proposals: AztecAsyncMap<
21
25
  /* proposal.payload.archive */ string,
22
26
  /* buffer representation of proposal */ Buffer
23
27
  >;
24
- private proposalsForSlot: AztecAsyncMultiMap<number, string>;
25
- private attestationsForProposal: AztecAsyncMultiMap<string, string>;
28
+
29
+ // Checkpoint attestation storage
30
+ private checkpointAttestations: AztecAsyncMap<string, Buffer>;
31
+ private checkpointProposals: AztecAsyncMap<string, Buffer>;
32
+ private checkpointProposalsForSlot: AztecAsyncMultiMap<number, string>;
33
+ private checkpointAttestationsForProposal: AztecAsyncMultiMap<string, string>;
26
34
 
27
35
  constructor(
28
36
  private store: AztecAsyncKVStore,
29
37
  telemetry: TelemetryClient = getTelemetryClient(),
30
38
  private log = createLogger('aztec:attestation_pool'),
31
39
  ) {
32
- this.attestations = store.openMap('attestations');
33
40
  this.proposals = store.openMap('proposals');
34
- this.proposalsForSlot = store.openMultiMap('proposals_for_slot');
35
- this.attestationsForProposal = store.openMultiMap('attestations_for_proposal');
41
+
42
+ // Initialize checkpoint attestation storage
43
+ this.checkpointAttestations = store.openMap('checkpoint_attestations');
44
+ this.checkpointProposals = store.openMap('checkpoint_proposals');
45
+ this.checkpointProposalsForSlot = store.openMultiMap('checkpoint_proposals_for_slot');
46
+ this.checkpointAttestationsForProposal = store.openMultiMap('checkpoint_attestations_for_proposal');
36
47
 
37
48
  this.metrics = new PoolInstrumentation(telemetry, PoolName.ATTESTATION_POOL, this.poolStats);
38
49
  }
39
50
 
40
51
  private poolStats: PoolStatsCallback = async () => {
41
52
  return {
42
- itemCount: await this.attestations.sizeAsync(),
53
+ itemCount: await this.checkpointAttestations.sizeAsync(),
43
54
  };
44
55
  };
45
56
 
46
57
  public async isEmpty(): Promise<boolean> {
47
- for await (const _ of this.attestations.entriesAsync()) {
58
+ for await (const _ of this.checkpointAttestations.entriesAsync()) {
59
+ return false;
60
+ }
61
+ for await (const _ of this.proposals.entriesAsync()) {
48
62
  return false;
49
63
  }
50
64
  return true;
@@ -66,7 +80,81 @@ export class KvAttestationPool implements AttestationPool {
66
80
  return `${this.getProposalKey(slot, proposalId)}-${address}`;
67
81
  }
68
82
 
69
- public async addAttestations(attestations: BlockAttestation[]): Promise<void> {
83
+ public async addBlockProposal(blockProposal: BlockProposal): Promise<void> {
84
+ await this.store.transactionAsync(async () => {
85
+ const proposalId = blockProposal.archive.toString();
86
+ // Strip signedTxs before storing to avoid persisting full tx data
87
+ await this.proposals.set(proposalId, blockProposal.withoutSignedTxs().toBuffer());
88
+ });
89
+ }
90
+
91
+ public async getBlockProposal(id: string): Promise<BlockProposal | undefined> {
92
+ const buffer = await this.proposals.getAsync(id);
93
+ try {
94
+ if (buffer && buffer.length > 0) {
95
+ return BlockProposal.fromBuffer(buffer);
96
+ }
97
+ } catch {
98
+ return Promise.resolve(undefined);
99
+ }
100
+
101
+ return Promise.resolve(undefined);
102
+ }
103
+
104
+ public async hasBlockProposal(idOrProposal: string | BlockProposal): Promise<boolean> {
105
+ const id = typeof idOrProposal === 'string' ? idOrProposal : idOrProposal.archive.toString();
106
+ return await this.proposals.hasAsync(id);
107
+ }
108
+
109
+ public async addCheckpointProposal(proposal: CheckpointProposal): Promise<void> {
110
+ if (!(await this.canAddCheckpointProposal(proposal))) {
111
+ throw new ProposalSlotCapExceededError(
112
+ `Maximum checkpoint proposals per slot reached: slot=${proposal.slotNumber} cap=${MAX_PROPOSALS_PER_SLOT} proposal=${proposal.archive.toString()}`,
113
+ );
114
+ }
115
+
116
+ // Extract and validate the block proposal if present
117
+ const blockProposal = proposal.getBlockProposal();
118
+ if (blockProposal && !(await this.canAddProposal(blockProposal))) {
119
+ throw new ProposalSlotCapExceededError(
120
+ `Maximum block proposals per slot reached when extracting from checkpoint: slot=${proposal.slotNumber} proposal=${blockProposal.archive.toString()}`,
121
+ );
122
+ }
123
+
124
+ await this.store.transactionAsync(async () => {
125
+ const slotKey = proposal.slotNumber;
126
+ const proposalId = proposal.archive.toString();
127
+
128
+ await this.checkpointProposalsForSlot.set(slotKey, proposalId);
129
+ // Store the checkpoint proposal as core (without lastBlock) to avoid duplication
130
+ await this.checkpointProposals.set(proposalId, proposal.toCore().toBuffer());
131
+
132
+ // Store the extracted block proposal separately
133
+ if (blockProposal) {
134
+ await this.proposals.set(blockProposal.archive.toString(), blockProposal.withoutSignedTxs().toBuffer());
135
+ }
136
+ });
137
+ }
138
+
139
+ public async getCheckpointProposal(id: string): Promise<CheckpointProposalCore | undefined> {
140
+ const buffer = await this.checkpointProposals.getAsync(id);
141
+ try {
142
+ if (buffer && buffer.length > 0) {
143
+ return CheckpointProposal.fromBuffer(buffer);
144
+ }
145
+ } catch {
146
+ return Promise.resolve(undefined);
147
+ }
148
+
149
+ return Promise.resolve(undefined);
150
+ }
151
+
152
+ public async hasCheckpointProposal(idOrProposal: string | CheckpointProposal): Promise<boolean> {
153
+ const id = typeof idOrProposal === 'string' ? idOrProposal : idOrProposal.archive.toString();
154
+ return await this.checkpointProposals.hasAsync(id);
155
+ }
156
+
157
+ public async addCheckpointAttestations(attestations: CheckpointAttestation[]): Promise<void> {
70
158
  await this.store.transactionAsync(async () => {
71
159
  for (const attestation of attestations) {
72
160
  const slotNumber = attestation.payload.header.slotNumber;
@@ -75,7 +163,7 @@ export class KvAttestationPool implements AttestationPool {
75
163
 
76
164
  // Skip attestations with invalid signatures
77
165
  if (!sender) {
78
- this.log.warn(`Skipping attestation with invalid signature for slot ${slotNumber}`, {
166
+ this.log.warn(`Skipping checkpoint attestation with invalid signature for slot ${slotNumber}`, {
79
167
  signature: attestation.signature.toString(),
80
168
  slotNumber,
81
169
  proposalId,
@@ -85,15 +173,18 @@ export class KvAttestationPool implements AttestationPool {
85
173
 
86
174
  const address = sender.toString();
87
175
 
88
- await this.attestations.set(this.getAttestationKey(slotNumber, proposalId, address), attestation.toBuffer());
176
+ await this.checkpointAttestations.set(
177
+ this.getAttestationKey(slotNumber, proposalId, address),
178
+ attestation.toBuffer(),
179
+ );
89
180
 
90
- await this.proposalsForSlot.set(slotNumber, proposalId.toString());
91
- await this.attestationsForProposal.set(
181
+ await this.checkpointProposalsForSlot.set(slotNumber, proposalId.toString());
182
+ await this.checkpointAttestationsForProposal.set(
92
183
  this.getProposalKey(slotNumber, proposalId),
93
184
  this.getAttestationKey(slotNumber, proposalId, address),
94
185
  );
95
186
 
96
- this.log.verbose(`Added attestation for slot ${slotNumber} from ${address}`, {
187
+ this.log.verbose(`Added checkpoint attestation for slot ${slotNumber} from ${address}`, {
97
188
  signature: attestation.signature.toString(),
98
189
  slotNumber,
99
190
  address,
@@ -103,122 +194,72 @@ export class KvAttestationPool implements AttestationPool {
103
194
  });
104
195
  }
105
196
 
106
- public async getAttestationsForSlot(slot: SlotNumber): Promise<BlockAttestation[]> {
107
- const proposalIds = await toArray(this.proposalsForSlot.getValuesAsync(slot));
108
- const attestations: BlockAttestation[] = [];
197
+ public async getCheckpointAttestationsForSlot(slot: SlotNumber): Promise<CheckpointAttestation[]> {
198
+ const proposalIds = await toArray(this.checkpointProposalsForSlot.getValuesAsync(slot));
199
+ const attestations: CheckpointAttestation[] = [];
109
200
 
110
201
  for (const proposalId of proposalIds) {
111
- attestations.push(...(await this.getAttestationsForSlotAndProposal(slot, proposalId)));
202
+ attestations.push(...(await this.getCheckpointAttestationsForSlotAndProposal(slot, proposalId)));
112
203
  }
113
204
 
114
205
  return attestations;
115
206
  }
116
207
 
117
- public async getAttestationsForSlotAndProposal(slot: SlotNumber, proposalId: string): Promise<BlockAttestation[]> {
208
+ public async getCheckpointAttestationsForSlotAndProposal(
209
+ slot: SlotNumber,
210
+ proposalId: string,
211
+ ): Promise<CheckpointAttestation[]> {
118
212
  const attestationIds = await toArray(
119
- this.attestationsForProposal.getValuesAsync(this.getProposalKey(slot, proposalId)),
213
+ this.checkpointAttestationsForProposal.getValuesAsync(this.getProposalKey(slot, proposalId)),
120
214
  );
121
- const attestations: BlockAttestation[] = [];
215
+ const attestations: CheckpointAttestation[] = [];
122
216
 
123
- // alternatively iterate this.attestaions starting from slot-proposal-EthAddress.zero
124
217
  for (const id of attestationIds) {
125
- const buf = await this.attestations.getAsync(id);
218
+ const buf = await this.checkpointAttestations.getAsync(id);
126
219
 
127
220
  if (!buf) {
128
- // this should not happen unless we lost writes
129
- throw new Error('Attestation not found ' + id);
221
+ throw new Error('Checkpoint attestation not found ' + id);
130
222
  }
131
223
 
132
- const attestation = BlockAttestation.fromBuffer(buf);
224
+ const attestation = CheckpointAttestation.fromBuffer(buf);
133
225
  attestations.push(attestation);
134
226
  }
135
227
 
136
228
  return attestations;
137
229
  }
138
230
 
139
- public async deleteAttestationsOlderThan(oldestSlot: SlotNumber): Promise<void> {
140
- const olderThan = await toArray(this.proposalsForSlot.keysAsync({ end: oldestSlot }));
231
+ public async deleteCheckpointAttestationsOlderThan(oldestSlot: SlotNumber): Promise<void> {
232
+ const olderThan = await toArray(this.checkpointProposalsForSlot.keysAsync({ end: oldestSlot }));
141
233
  for (const oldSlot of olderThan) {
142
- await this.deleteAttestationsForSlot(SlotNumber(oldSlot));
234
+ await this.deleteCheckpointAttestationsForSlot(SlotNumber(oldSlot));
143
235
  }
144
236
  }
145
237
 
146
- public async deleteAttestationsForSlot(slot: SlotNumber): Promise<void> {
238
+ private async deleteCheckpointAttestationsForSlot(slot: SlotNumber): Promise<void> {
147
239
  let numberOfAttestations = 0;
148
240
  await this.store.transactionAsync(async () => {
149
- const proposalIds = await toArray(this.proposalsForSlot.getValuesAsync(slot));
241
+ const proposalIds = await toArray(this.checkpointProposalsForSlot.getValuesAsync(slot));
150
242
  for (const proposalId of proposalIds) {
151
243
  const attestations = await toArray(
152
- this.attestationsForProposal.getValuesAsync(this.getProposalKey(slot, proposalId)),
244
+ this.checkpointAttestationsForProposal.getValuesAsync(this.getProposalKey(slot, proposalId)),
153
245
  );
154
246
 
155
247
  numberOfAttestations += attestations.length;
156
248
  for (const attestation of attestations) {
157
- await this.attestations.delete(attestation);
249
+ await this.checkpointAttestations.delete(attestation);
158
250
  }
159
251
 
160
- await this.proposals.delete(proposalId);
161
- await this.attestationsForProposal.delete(this.getProposalKey(slot, proposalId));
252
+ await this.checkpointProposals.delete(proposalId);
253
+ await this.checkpointAttestationsForProposal.delete(this.getProposalKey(slot, proposalId));
162
254
  }
163
255
 
164
- // Delete from proposalsForSlot
165
- await this.proposalsForSlot.delete(slot);
256
+ await this.checkpointProposalsForSlot.delete(slot);
166
257
 
167
- this.log.verbose(`Removed ${numberOfAttestations} attestations for slot ${slot}`);
258
+ this.log.verbose(`Removed ${numberOfAttestations} checkpoint attestations for slot ${slot}`);
168
259
  });
169
260
  }
170
261
 
171
- public async deleteAttestationsForSlotAndProposal(slot: SlotNumber, proposalId: string): Promise<void> {
172
- let numberOfAttestations = 0;
173
- await this.store.transactionAsync(async () => {
174
- const attestations = await toArray(
175
- this.attestationsForProposal.getValuesAsync(this.getProposalKey(slot, proposalId)),
176
- );
177
-
178
- numberOfAttestations += attestations.length;
179
- for (const attestation of attestations) {
180
- await this.attestations.delete(attestation);
181
- }
182
-
183
- await this.proposals.delete(proposalId);
184
- await this.proposalsForSlot.deleteValue(slot, proposalId);
185
- await this.attestationsForProposal.delete(this.getProposalKey(slot, proposalId));
186
-
187
- this.log.verbose(`Removed ${numberOfAttestations} attestations for slot ${slot} and proposal ${proposalId}`);
188
- });
189
- }
190
-
191
- public async deleteAttestations(attestations: BlockAttestation[]): Promise<void> {
192
- await this.store.transactionAsync(async () => {
193
- for (const attestation of attestations) {
194
- const slotNumber = attestation.payload.header.slotNumber;
195
- const proposalId = attestation.archive;
196
- const sender = attestation.getSender();
197
-
198
- // Skip attestations with invalid signatures
199
- if (!sender) {
200
- this.log.warn(`Skipping deletion of attestation with invalid signature for slot ${slotNumber}`);
201
- continue;
202
- }
203
-
204
- const address = sender.toString();
205
- const key = this.getAttestationKey(slotNumber, proposalId, address);
206
-
207
- if (await this.attestations.hasAsync(key)) {
208
- await this.attestations.delete(key);
209
- }
210
-
211
- await this.attestationsForProposal.deleteValue(
212
- this.getProposalKey(slotNumber, proposalId),
213
- this.getAttestationKey(slotNumber, proposalId, address),
214
- );
215
-
216
- this.log.debug(`Deleted attestation for slot ${slotNumber} from ${address}`);
217
- }
218
- });
219
- }
220
-
221
- public async hasAttestation(attestation: BlockAttestation): Promise<boolean> {
262
+ public async hasCheckpointAttestation(attestation: CheckpointAttestation): Promise<boolean> {
222
263
  const slotNumber = attestation.payload.header.slotNumber;
223
264
  const proposalId = attestation.archive;
224
265
  const sender = attestation.getSender();
@@ -231,68 +272,49 @@ export class KvAttestationPool implements AttestationPool {
231
272
  const address = sender.toString();
232
273
  const key = this.getAttestationKey(slotNumber, proposalId, address);
233
274
 
234
- return await this.attestations.hasAsync(key);
275
+ return await this.checkpointAttestations.hasAsync(key);
235
276
  }
236
277
 
237
- public async getBlockProposal(id: string): Promise<BlockProposal | undefined> {
238
- const buffer = await this.proposals.getAsync(id);
239
- try {
240
- if (buffer && buffer.length > 0) {
241
- return BlockProposal.fromBuffer(buffer);
242
- }
243
- } catch {
244
- return Promise.resolve(undefined);
245
- }
246
-
247
- return Promise.resolve(undefined);
248
- }
249
-
250
- public async hasBlockProposal(idOrProposal: string | BlockProposal): Promise<boolean> {
251
- const id = typeof idOrProposal === 'string' ? idOrProposal : idOrProposal.payload.archive.toString();
252
- return await this.proposals.hasAsync(id);
278
+ public canAddProposal(_block: BlockProposal): Promise<boolean> {
279
+ // TODO(palla/mbps): implement proposal cap logic
280
+ return Promise.resolve(true);
253
281
  }
254
282
 
255
- public async addBlockProposal(blockProposal: BlockProposal): Promise<void> {
256
- await this.store.transactionAsync(async () => {
257
- const slotKey = blockProposal.slotNumber;
258
- const proposalId = blockProposal.archive.toString();
259
-
260
- if (!(await this.canAddProposal(blockProposal))) {
261
- throw new ProposalSlotCapExceededError(
262
- `Maximum proposals per slot reached: slot=${slotKey} cap=${MAX_PROPOSALS_PER_SLOT} proposal=${proposalId}`,
263
- );
264
- }
265
-
266
- await this.proposalsForSlot.set(slotKey, proposalId);
267
- // Always update the stored proposal buffer so re-adds overwrite with latest data
268
- await this.proposals.set(proposalId, blockProposal.toBuffer());
269
- });
270
- }
271
-
272
- public async hasReachedProposalCap(slot: SlotNumber): Promise<boolean> {
273
- const uniqueProposalCount = await this.proposalsForSlot.getValueCountAsync(slot);
274
- return uniqueProposalCount >= MAX_PROPOSALS_PER_SLOT;
275
- }
276
-
277
- public async hasReachedAttestationCap(slot: SlotNumber, proposalId: string, committeeSize: number): Promise<boolean> {
278
- const limit = committeeSize + ATTESTATION_CAP_BUFFER;
279
- return (await this.attestationsForProposal.getValueCountAsync(this.getProposalKey(slot, proposalId))) >= limit;
280
- }
281
-
282
- public async canAddProposal(block: BlockProposal): Promise<boolean> {
283
+ public async canAddCheckpointProposal(proposal: CheckpointProposal): Promise<boolean> {
284
+ // TODO(palla/mbps): Adjust checkpoint proposal limit to 1. Also connect to slashing condition in the caller.
283
285
  return (
284
- (await this.proposals.hasAsync(block.archive.toString())) || !(await this.hasReachedProposalCap(block.slotNumber))
286
+ (await this.checkpointProposals.hasAsync(proposal.archive.toString())) ||
287
+ !(await this.hasReachedCheckpointProposalCap(proposal.slotNumber))
285
288
  );
286
289
  }
287
290
 
288
- public async canAddAttestation(attestation: BlockAttestation, committeeSize: number): Promise<boolean> {
291
+ public async canAddCheckpointAttestation(
292
+ attestation: CheckpointAttestation,
293
+ committeeSize: number,
294
+ ): Promise<boolean> {
289
295
  return (
290
- (await this.hasAttestation(attestation)) ||
291
- !(await this.hasReachedAttestationCap(
296
+ (await this.hasCheckpointAttestation(attestation)) ||
297
+ !(await this.hasReachedCheckpointAttestationCap(
292
298
  attestation.payload.header.slotNumber,
293
299
  attestation.archive.toString(),
294
300
  committeeSize,
295
301
  ))
296
302
  );
297
303
  }
304
+
305
+ public async hasReachedCheckpointProposalCap(slot: SlotNumber): Promise<boolean> {
306
+ const uniqueProposalCount = await this.checkpointProposalsForSlot.getValueCountAsync(slot);
307
+ return uniqueProposalCount >= MAX_PROPOSALS_PER_SLOT;
308
+ }
309
+
310
+ public async hasReachedCheckpointAttestationCap(
311
+ slot: SlotNumber,
312
+ proposalId: string,
313
+ committeeSize: number,
314
+ ): Promise<boolean> {
315
+ const limit = committeeSize + ATTESTATION_CAP_BUFFER;
316
+ return (
317
+ (await this.checkpointAttestationsForProposal.getValueCountAsync(this.getProposalKey(slot, proposalId))) >= limit
318
+ );
319
+ }
298
320
  }