@aztec/p2p 0.0.1-commit.b655e406 → 0.0.1-commit.d3ec352c

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 (239) hide show
  1. package/dest/bootstrap/bootstrap.d.ts +1 -1
  2. package/dest/bootstrap/bootstrap.d.ts.map +1 -1
  3. package/dest/client/factory.d.ts +1 -1
  4. package/dest/client/index.d.ts +1 -1
  5. package/dest/client/interface.d.ts +4 -2
  6. package/dest/client/interface.d.ts.map +1 -1
  7. package/dest/client/p2p_client.d.ts +8 -26
  8. package/dest/client/p2p_client.d.ts.map +1 -1
  9. package/dest/client/p2p_client.js +22 -16
  10. package/dest/config.d.ts +60 -54
  11. package/dest/config.d.ts.map +1 -1
  12. package/dest/config.js +11 -1
  13. package/dest/enr/generate-enr.d.ts +1 -1
  14. package/dest/enr/index.d.ts +1 -1
  15. package/dest/errors/attestation-pool.error.d.ts +7 -0
  16. package/dest/errors/attestation-pool.error.d.ts.map +1 -0
  17. package/dest/errors/attestation-pool.error.js +12 -0
  18. package/dest/errors/reqresp.error.d.ts +1 -1
  19. package/dest/errors/reqresp.error.d.ts.map +1 -1
  20. package/dest/index.d.ts +1 -1
  21. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +28 -6
  22. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
  23. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts +1 -1
  24. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts.map +1 -1
  25. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.js +33 -32
  26. package/dest/mem_pools/attestation_pool/index.d.ts +1 -1
  27. package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts +13 -6
  28. package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts.map +1 -1
  29. package/dest/mem_pools/attestation_pool/kv_attestation_pool.js +40 -17
  30. package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts +11 -6
  31. package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts.map +1 -1
  32. package/dest/mem_pools/attestation_pool/memory_attestation_pool.js +30 -8
  33. package/dest/mem_pools/attestation_pool/mocks.d.ts +224 -3
  34. package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -1
  35. package/dest/mem_pools/attestation_pool/mocks.js +1 -1
  36. package/dest/mem_pools/index.d.ts +1 -1
  37. package/dest/mem_pools/instrumentation.d.ts +3 -1
  38. package/dest/mem_pools/instrumentation.d.ts.map +1 -1
  39. package/dest/mem_pools/instrumentation.js +11 -2
  40. package/dest/mem_pools/interface.d.ts +1 -1
  41. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts +4 -38
  42. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts.map +1 -1
  43. package/dest/mem_pools/tx_pool/index.d.ts +1 -1
  44. package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts +4 -3
  45. package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts.map +1 -1
  46. package/dest/mem_pools/tx_pool/memory_tx_pool.js +1 -0
  47. package/dest/mem_pools/tx_pool/priority.d.ts +1 -1
  48. package/dest/mem_pools/tx_pool/tx_pool.d.ts +4 -3
  49. package/dest/mem_pools/tx_pool/tx_pool.d.ts.map +1 -1
  50. package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts +1 -1
  51. package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts.map +1 -1
  52. package/dest/mem_pools/tx_pool/tx_pool_test_suite.js +5 -4
  53. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +4 -3
  54. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -1
  55. package/dest/msg_validators/attestation_validator/attestation_validator.js +11 -11
  56. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts +20 -0
  57. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts.map +1 -0
  58. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.js +67 -0
  59. package/dest/msg_validators/attestation_validator/index.d.ts +2 -1
  60. package/dest/msg_validators/attestation_validator/index.d.ts.map +1 -1
  61. package/dest/msg_validators/attestation_validator/index.js +1 -0
  62. package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts +1 -1
  63. package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts.map +1 -1
  64. package/dest/msg_validators/block_proposal_validator/block_proposal_validator.js +21 -9
  65. package/dest/msg_validators/block_proposal_validator/index.d.ts +1 -1
  66. package/dest/msg_validators/index.d.ts +1 -1
  67. package/dest/msg_validators/msg_seen_validator/msg_seen_validator.d.ts +1 -1
  68. package/dest/msg_validators/msg_seen_validator/msg_seen_validator.d.ts.map +1 -1
  69. package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts +1 -1
  70. package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts.map +1 -1
  71. package/dest/msg_validators/tx_validator/allowed_public_setup.d.ts +1 -1
  72. package/dest/msg_validators/tx_validator/archive_cache.d.ts +1 -1
  73. package/dest/msg_validators/tx_validator/archive_cache.d.ts.map +1 -1
  74. package/dest/msg_validators/tx_validator/block_header_validator.d.ts +1 -1
  75. package/dest/msg_validators/tx_validator/block_header_validator.d.ts.map +1 -1
  76. package/dest/msg_validators/tx_validator/data_validator.d.ts +1 -1
  77. package/dest/msg_validators/tx_validator/data_validator.d.ts.map +1 -1
  78. package/dest/msg_validators/tx_validator/double_spend_validator.d.ts +1 -1
  79. package/dest/msg_validators/tx_validator/double_spend_validator.d.ts.map +1 -1
  80. package/dest/msg_validators/tx_validator/factory.d.ts +3 -2
  81. package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -1
  82. package/dest/msg_validators/tx_validator/gas_validator.d.ts +1 -1
  83. package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -1
  84. package/dest/msg_validators/tx_validator/index.d.ts +1 -1
  85. package/dest/msg_validators/tx_validator/metadata_validator.d.ts +1 -1
  86. package/dest/msg_validators/tx_validator/metadata_validator.d.ts.map +1 -1
  87. package/dest/msg_validators/tx_validator/phases_validator.d.ts +1 -1
  88. package/dest/msg_validators/tx_validator/phases_validator.d.ts.map +1 -1
  89. package/dest/msg_validators/tx_validator/phases_validator.js +3 -1
  90. package/dest/msg_validators/tx_validator/test_utils.d.ts +1 -1
  91. package/dest/msg_validators/tx_validator/timestamp_validator.d.ts +3 -2
  92. package/dest/msg_validators/tx_validator/timestamp_validator.d.ts.map +1 -1
  93. package/dest/msg_validators/tx_validator/tx_permitted_validator.d.ts +1 -1
  94. package/dest/msg_validators/tx_validator/tx_permitted_validator.d.ts.map +1 -1
  95. package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts +1 -1
  96. package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts.map +1 -1
  97. package/dest/services/data_store.d.ts +1 -1
  98. package/dest/services/data_store.d.ts.map +1 -1
  99. package/dest/services/discv5/discV5_service.d.ts +1 -1
  100. package/dest/services/discv5/discV5_service.d.ts.map +1 -1
  101. package/dest/services/dummy_service.d.ts +1 -1
  102. package/dest/services/dummy_service.d.ts.map +1 -1
  103. package/dest/services/encoding.d.ts +1 -1
  104. package/dest/services/encoding.d.ts.map +1 -1
  105. package/dest/services/gossipsub/scoring.d.ts +1 -1
  106. package/dest/services/index.d.ts +1 -1
  107. package/dest/services/libp2p/instrumentation.d.ts +3 -1
  108. package/dest/services/libp2p/instrumentation.d.ts.map +1 -1
  109. package/dest/services/libp2p/instrumentation.js +9 -2
  110. package/dest/services/libp2p/libp2p_service.d.ts +11 -67
  111. package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
  112. package/dest/services/libp2p/libp2p_service.js +227 -57
  113. package/dest/services/peer-manager/interface.d.ts +1 -1
  114. package/dest/services/peer-manager/metrics.d.ts +3 -1
  115. package/dest/services/peer-manager/metrics.d.ts.map +1 -1
  116. package/dest/services/peer-manager/metrics.js +11 -0
  117. package/dest/services/peer-manager/peer_manager.d.ts +1 -32
  118. package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
  119. package/dest/services/peer-manager/peer_manager.js +2 -0
  120. package/dest/services/peer-manager/peer_scoring.d.ts +7 -2
  121. package/dest/services/peer-manager/peer_scoring.d.ts.map +1 -1
  122. package/dest/services/peer-manager/peer_scoring.js +40 -2
  123. package/dest/services/reqresp/config.d.ts +1 -1
  124. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts +1 -1
  125. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts.map +1 -1
  126. package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts +1 -4
  127. package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts.map +1 -1
  128. package/dest/services/reqresp/index.d.ts +1 -1
  129. package/dest/services/reqresp/interface.d.ts +1 -1
  130. package/dest/services/reqresp/interface.d.ts.map +1 -1
  131. package/dest/services/reqresp/metrics.d.ts +1 -1
  132. package/dest/services/reqresp/metrics.d.ts.map +1 -1
  133. package/dest/services/reqresp/protocols/auth.d.ts +1 -1
  134. package/dest/services/reqresp/protocols/auth.d.ts.map +1 -1
  135. package/dest/services/reqresp/protocols/block.d.ts +1 -1
  136. package/dest/services/reqresp/protocols/block.d.ts.map +1 -1
  137. package/dest/services/reqresp/protocols/block.js +2 -1
  138. package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts +1 -1
  139. package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts.map +1 -1
  140. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts +1 -1
  141. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts +3 -5
  142. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts.map +1 -1
  143. package/dest/services/reqresp/protocols/block_txs/index.d.ts +1 -1
  144. package/dest/services/reqresp/protocols/goodbye.d.ts +1 -1
  145. package/dest/services/reqresp/protocols/goodbye.d.ts.map +1 -1
  146. package/dest/services/reqresp/protocols/index.d.ts +1 -1
  147. package/dest/services/reqresp/protocols/ping.d.ts +1 -1
  148. package/dest/services/reqresp/protocols/status.d.ts +6 -5
  149. package/dest/services/reqresp/protocols/status.d.ts.map +1 -1
  150. package/dest/services/reqresp/protocols/status.js +4 -3
  151. package/dest/services/reqresp/protocols/tx.d.ts +1 -1
  152. package/dest/services/reqresp/rate-limiter/index.d.ts +1 -1
  153. package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts +2 -2
  154. package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts.map +1 -1
  155. package/dest/services/reqresp/rate-limiter/rate_limits.d.ts +1 -1
  156. package/dest/services/reqresp/reqresp.d.ts +1 -41
  157. package/dest/services/reqresp/reqresp.d.ts.map +1 -1
  158. package/dest/services/reqresp/status.d.ts +2 -2
  159. package/dest/services/reqresp/status.d.ts.map +1 -1
  160. package/dest/services/service.d.ts +1 -1
  161. package/dest/services/tx_collection/config.d.ts +1 -1
  162. package/dest/services/tx_collection/fast_tx_collection.d.ts +4 -9
  163. package/dest/services/tx_collection/fast_tx_collection.d.ts.map +1 -1
  164. package/dest/services/tx_collection/index.d.ts +1 -1
  165. package/dest/services/tx_collection/instrumentation.d.ts +1 -1
  166. package/dest/services/tx_collection/instrumentation.d.ts.map +1 -1
  167. package/dest/services/tx_collection/slow_tx_collection.d.ts +4 -5
  168. package/dest/services/tx_collection/slow_tx_collection.d.ts.map +1 -1
  169. package/dest/services/tx_collection/slow_tx_collection.js +2 -1
  170. package/dest/services/tx_collection/tx_collection.d.ts +9 -9
  171. package/dest/services/tx_collection/tx_collection.d.ts.map +1 -1
  172. package/dest/services/tx_collection/tx_collection.js +1 -1
  173. package/dest/services/tx_collection/tx_collection_sink.d.ts +3 -3
  174. package/dest/services/tx_collection/tx_collection_sink.d.ts.map +1 -1
  175. package/dest/services/tx_collection/tx_source.d.ts +1 -1
  176. package/dest/services/tx_collection/tx_source.d.ts.map +1 -1
  177. package/dest/services/tx_provider.d.ts +5 -4
  178. package/dest/services/tx_provider.d.ts.map +1 -1
  179. package/dest/services/tx_provider_instrumentation.d.ts +1 -1
  180. package/dest/services/tx_provider_instrumentation.d.ts.map +1 -1
  181. package/dest/test-helpers/generate-peer-id-private-keys.d.ts +1 -1
  182. package/dest/test-helpers/get-ports.d.ts +1 -1
  183. package/dest/test-helpers/get-ports.d.ts.map +1 -1
  184. package/dest/test-helpers/index.d.ts +1 -1
  185. package/dest/test-helpers/make-enrs.d.ts +1 -1
  186. package/dest/test-helpers/make-test-p2p-clients.d.ts +2 -2
  187. package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -1
  188. package/dest/test-helpers/mock-pubsub.d.ts +4 -4
  189. package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
  190. package/dest/test-helpers/mock-tx-helpers.d.ts +2 -2
  191. package/dest/test-helpers/mock-tx-helpers.d.ts.map +1 -1
  192. package/dest/test-helpers/reqresp-nodes.d.ts +1 -1
  193. package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -1
  194. package/dest/testbench/p2p_client_testbench_worker.d.ts +1 -1
  195. package/dest/testbench/p2p_client_testbench_worker.js +11 -8
  196. package/dest/testbench/parse_log_file.d.ts +1 -1
  197. package/dest/testbench/testbench.d.ts +1 -1
  198. package/dest/testbench/worker_client_manager.d.ts +1 -1
  199. package/dest/testbench/worker_client_manager.d.ts.map +1 -1
  200. package/dest/types/index.d.ts +1 -1
  201. package/dest/util.d.ts +2 -1
  202. package/dest/util.d.ts.map +1 -1
  203. package/dest/util.js +11 -2
  204. package/dest/versioning.d.ts +1 -1
  205. package/package.json +19 -18
  206. package/src/client/interface.ts +4 -1
  207. package/src/client/p2p_client.ts +37 -29
  208. package/src/config.ts +18 -1
  209. package/src/errors/attestation-pool.error.ts +13 -0
  210. package/src/mem_pools/attestation_pool/attestation_pool.ts +29 -5
  211. package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +45 -32
  212. package/src/mem_pools/attestation_pool/kv_attestation_pool.ts +65 -23
  213. package/src/mem_pools/attestation_pool/memory_attestation_pool.ts +50 -16
  214. package/src/mem_pools/attestation_pool/mocks.ts +1 -1
  215. package/src/mem_pools/instrumentation.ts +13 -0
  216. package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +7 -6
  217. package/src/mem_pools/tx_pool/memory_tx_pool.ts +8 -6
  218. package/src/mem_pools/tx_pool/tx_pool.ts +3 -2
  219. package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +5 -4
  220. package/src/msg_validators/attestation_validator/attestation_validator.ts +13 -15
  221. package/src/msg_validators/attestation_validator/fisherman_attestation_validator.ts +91 -0
  222. package/src/msg_validators/attestation_validator/index.ts +1 -0
  223. package/src/msg_validators/block_proposal_validator/block_proposal_validator.ts +25 -9
  224. package/src/msg_validators/tx_validator/factory.ts +2 -1
  225. package/src/msg_validators/tx_validator/phases_validator.ts +3 -1
  226. package/src/msg_validators/tx_validator/timestamp_validator.ts +2 -1
  227. package/src/services/libp2p/instrumentation.ts +10 -1
  228. package/src/services/libp2p/libp2p_service.ts +255 -66
  229. package/src/services/peer-manager/metrics.ts +10 -0
  230. package/src/services/peer-manager/peer_manager.ts +2 -0
  231. package/src/services/peer-manager/peer_scoring.ts +46 -3
  232. package/src/services/reqresp/protocols/block.ts +2 -1
  233. package/src/services/reqresp/protocols/status.ts +9 -8
  234. package/src/services/tx_collection/fast_tx_collection.ts +3 -2
  235. package/src/services/tx_collection/slow_tx_collection.ts +5 -4
  236. package/src/services/tx_collection/tx_collection.ts +9 -8
  237. package/src/services/tx_provider.ts +4 -3
  238. package/src/testbench/p2p_client_testbench_worker.ts +8 -5
  239. package/src/util.ts +12 -2
@@ -1,3 +1,4 @@
1
+ import { SlotNumber } from '@aztec/foundation/branded-types';
1
2
  import { Secp256k1Signer } from '@aztec/foundation/crypto';
2
3
  import { Fr } from '@aztec/foundation/fields';
3
4
  import type { BlockAttestation, BlockProposal } from '@aztec/stdlib/p2p';
@@ -42,7 +43,7 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
42
43
 
43
44
  const mockBlockProposal = (signer: Secp256k1Signer, slotNumber: number, archive: Fr = Fr.random()): BlockProposal => {
44
45
  const header = makeL2BlockHeader(1, 2, slotNumber);
45
- const payload = new ConsensusPayload(header.toCheckpointHeader(), archive, header.state);
46
+ const payload = new ConsensusPayload(header.toCheckpointHeader(), archive);
46
47
 
47
48
  const hash = getHashedSignaturePayloadEthSignedMessage(payload, SignatureDomainSeparator.blockProposal);
48
49
  const signature = signer.sign(hash);
@@ -68,7 +69,10 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
68
69
 
69
70
  await ap.addAttestations(attestations);
70
71
 
71
- const retrievedAttestations = await ap.getAttestationsForSlotAndProposal(BigInt(slotNumber), archive.toString());
72
+ const retrievedAttestations = await ap.getAttestationsForSlotAndProposal(
73
+ SlotNumber(slotNumber),
74
+ archive.toString(),
75
+ );
72
76
  expect(retrievedAttestations.length).toBe(attestations.length);
73
77
  compareAttestations(retrievedAttestations, attestations);
74
78
 
@@ -77,7 +81,7 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
77
81
  expect(await ap.hasAttestation(attestation)).toBe(true);
78
82
  }
79
83
 
80
- const retrievedAttestationsForSlot = await ap.getAttestationsForSlot(BigInt(slotNumber));
84
+ const retrievedAttestationsForSlot = await ap.getAttestationsForSlot(SlotNumber(slotNumber));
81
85
  expect(retrievedAttestationsForSlot.length).toBe(attestations.length);
82
86
  compareAttestations(retrievedAttestationsForSlot, attestations);
83
87
 
@@ -85,21 +89,21 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
85
89
  const newAttestation = mockAttestation(signers[NUMBER_OF_SIGNERS_PER_TEST - 1], slotNumber, archive);
86
90
  await ap.addAttestations([newAttestation]);
87
91
  const retrievedAttestationsAfterAdd = await ap.getAttestationsForSlotAndProposal(
88
- BigInt(slotNumber),
92
+ SlotNumber(slotNumber),
89
93
  archive.toString(),
90
94
  );
91
95
  expect(retrievedAttestationsAfterAdd.length).toBe(attestations.length + 1);
92
96
  compareAttestations(retrievedAttestationsAfterAdd, [...attestations, newAttestation]);
93
97
  expect(await ap.hasAttestation(newAttestation)).toBe(true);
94
- const retrievedAttestationsForSlotAfterAdd = await ap.getAttestationsForSlot(BigInt(slotNumber));
98
+ const retrievedAttestationsForSlotAfterAdd = await ap.getAttestationsForSlot(SlotNumber(slotNumber));
95
99
  expect(retrievedAttestationsForSlotAfterAdd.length).toBe(attestations.length + 1);
96
100
  compareAttestations(retrievedAttestationsForSlotAfterAdd, [...attestations, newAttestation]);
97
101
 
98
102
  // Delete by slot
99
- await ap.deleteAttestationsForSlot(BigInt(slotNumber));
103
+ await ap.deleteAttestationsForSlot(SlotNumber(slotNumber));
100
104
 
101
105
  const retreivedAttestationsAfterDelete = await ap.getAttestationsForSlotAndProposal(
102
- BigInt(slotNumber),
106
+ SlotNumber(slotNumber),
103
107
  archive.toString(),
104
108
  );
105
109
  expect(retreivedAttestationsAfterDelete.length).toBe(0);
@@ -124,14 +128,17 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
124
128
  // Add them to store and check we end up with only one
125
129
  await ap.addAttestations(attestations);
126
130
 
127
- const retreivedAttestations = await ap.getAttestationsForSlotAndProposal(BigInt(slotNumber), archive.toString());
131
+ const retreivedAttestations = await ap.getAttestationsForSlotAndProposal(
132
+ SlotNumber(slotNumber),
133
+ archive.toString(),
134
+ );
128
135
  expect(retreivedAttestations.length).toBe(1);
129
136
  expect(retreivedAttestations[0].toBuffer()).toEqual(attestations[0].toBuffer());
130
137
  expect(retreivedAttestations[0].getSender()?.toString()).toEqual(signer.address.toString());
131
138
 
132
139
  // Try adding them on another operation and check they are still not duplicated
133
140
  await ap.addAttestations([attestations[0]]);
134
- expect(await ap.getAttestationsForSlotAndProposal(BigInt(slotNumber), archive.toString())).toHaveLength(1);
141
+ expect(await ap.getAttestationsForSlotAndProposal(SlotNumber(slotNumber), archive.toString())).toHaveLength(1);
135
142
  });
136
143
 
137
144
  it('should store attestations by differing slot', async () => {
@@ -144,7 +151,7 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
144
151
  const slot = attestation.payload.header.slotNumber;
145
152
  const archive = attestation.archive.toString();
146
153
 
147
- const retreivedAttestations = await ap.getAttestationsForSlotAndProposal(slot.toBigInt(), archive);
154
+ const retreivedAttestations = await ap.getAttestationsForSlotAndProposal(slot, archive);
148
155
  expect(retreivedAttestations.length).toBe(1);
149
156
  expect(retreivedAttestations[0].toBuffer()).toEqual(attestation.toBuffer());
150
157
  expect(retreivedAttestations[0].payload.header.slotNumber).toEqual(slot);
@@ -162,7 +169,7 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
162
169
  const slot = attestation.payload.header.slotNumber;
163
170
  const proposalId = attestation.archive.toString();
164
171
 
165
- const retreivedAttestations = await ap.getAttestationsForSlotAndProposal(slot.toBigInt(), proposalId);
172
+ const retreivedAttestations = await ap.getAttestationsForSlotAndProposal(slot, proposalId);
166
173
  expect(retreivedAttestations.length).toBe(1);
167
174
  expect(retreivedAttestations[0].toBuffer()).toEqual(attestation.toBuffer());
168
175
  expect(retreivedAttestations[0].payload.header.slotNumber).toEqual(slot);
@@ -177,7 +184,7 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
177
184
 
178
185
  await ap.addAttestations(attestations);
179
186
 
180
- const retreivedAttestations = await ap.getAttestationsForSlotAndProposal(BigInt(slotNumber), proposalId);
187
+ const retreivedAttestations = await ap.getAttestationsForSlotAndProposal(SlotNumber(slotNumber), proposalId);
181
188
  expect(retreivedAttestations.length).toBe(NUMBER_OF_SIGNERS_PER_TEST);
182
189
  compareAttestations(retreivedAttestations, attestations);
183
190
 
@@ -188,7 +195,7 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
188
195
 
189
196
  await ap.deleteAttestations(attestations);
190
197
 
191
- const gottenAfterDelete = await ap.getAttestationsForSlotAndProposal(BigInt(slotNumber), proposalId);
198
+ const gottenAfterDelete = await ap.getAttestationsForSlotAndProposal(SlotNumber(slotNumber), proposalId);
192
199
  expect(gottenAfterDelete.length).toBe(0);
193
200
 
194
201
  // Check hasAttestation after deletion
@@ -205,13 +212,16 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
205
212
 
206
213
  await ap.addAttestations(attestations);
207
214
 
208
- const retreivedAttestations = await ap.getAttestationsForSlotAndProposal(BigInt(slotNumber), proposalId);
215
+ const retreivedAttestations = await ap.getAttestationsForSlotAndProposal(SlotNumber(slotNumber), proposalId);
209
216
  expect(retreivedAttestations.length).toBe(NUMBER_OF_SIGNERS_PER_TEST);
210
217
  compareAttestations(retreivedAttestations, attestations);
211
218
 
212
- await ap.deleteAttestationsForSlot(BigInt(slotNumber));
219
+ await ap.deleteAttestationsForSlot(SlotNumber(slotNumber));
213
220
 
214
- const retreivedAttestationsAfterDelete = await ap.getAttestationsForSlotAndProposal(BigInt(slotNumber), proposalId);
221
+ const retreivedAttestationsAfterDelete = await ap.getAttestationsForSlotAndProposal(
222
+ SlotNumber(slotNumber),
223
+ proposalId,
224
+ );
215
225
  expect(retreivedAttestationsAfterDelete.length).toBe(0);
216
226
  });
217
227
 
@@ -229,17 +239,20 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
229
239
  await ap.addAttestations(attestations);
230
240
  await ap.addAttestations(attestations2);
231
241
 
232
- const retreivedAttestations = await ap.getAttestationsForSlotAndProposal(BigInt(slotNumber), proposalId);
242
+ const retreivedAttestations = await ap.getAttestationsForSlotAndProposal(SlotNumber(slotNumber), proposalId);
233
243
  expect(retreivedAttestations.length).toBe(NUMBER_OF_SIGNERS_PER_TEST);
234
244
  compareAttestations(retreivedAttestations, attestations);
235
245
 
236
- await ap.deleteAttestationsForSlotAndProposal(BigInt(slotNumber), proposalId);
246
+ await ap.deleteAttestationsForSlotAndProposal(SlotNumber(slotNumber), proposalId);
237
247
 
238
- const retreivedAttestationsAfterDelete = await ap.getAttestationsForSlotAndProposal(BigInt(slotNumber), proposalId);
248
+ const retreivedAttestationsAfterDelete = await ap.getAttestationsForSlotAndProposal(
249
+ SlotNumber(slotNumber),
250
+ proposalId,
251
+ );
239
252
  expect(retreivedAttestationsAfterDelete.length).toBe(0);
240
253
 
241
254
  const retreivedAttestationsAfterDeleteForOtherProposal = await ap.getAttestationsForSlotAndProposal(
242
- BigInt(slotNumber),
255
+ SlotNumber(slotNumber),
243
256
  proposalId2,
244
257
  );
245
258
  expect(retreivedAttestationsAfterDeleteForOtherProposal.length).toBe(NUMBER_OF_SIGNERS_PER_TEST);
@@ -255,22 +268,22 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
255
268
 
256
269
  await ap.addAttestations(attestations);
257
270
 
258
- const attestationsForSlot1 = await ap.getAttestationsForSlotAndProposal(BigInt(1), proposalId);
271
+ const attestationsForSlot1 = await ap.getAttestationsForSlotAndProposal(SlotNumber(1), proposalId);
259
272
  expect(attestationsForSlot1.length).toBe(signers.length);
260
273
 
261
274
  const deleteAttestationsSpy = jest.spyOn(ap, 'deleteAttestationsForSlot');
262
275
 
263
- await ap.deleteAttestationsOlderThan(BigInt(73));
276
+ await ap.deleteAttestationsOlderThan(SlotNumber(73));
264
277
 
265
- const attestationsForSlot1AfterDelete = await ap.getAttestationsForSlotAndProposal(BigInt(1), proposalId);
278
+ const attestationsForSlot1AfterDelete = await ap.getAttestationsForSlotAndProposal(SlotNumber(1), proposalId);
266
279
  expect(attestationsForSlot1AfterDelete.length).toBe(0);
267
280
 
268
281
  expect(deleteAttestationsSpy).toHaveBeenCalledTimes(5);
269
- expect(deleteAttestationsSpy).toHaveBeenCalledWith(BigInt(1));
270
- expect(deleteAttestationsSpy).toHaveBeenCalledWith(BigInt(2));
271
- expect(deleteAttestationsSpy).toHaveBeenCalledWith(BigInt(3));
272
- expect(deleteAttestationsSpy).toHaveBeenCalledWith(BigInt(69));
273
- expect(deleteAttestationsSpy).toHaveBeenCalledWith(BigInt(72));
282
+ expect(deleteAttestationsSpy).toHaveBeenCalledWith(SlotNumber(1));
283
+ expect(deleteAttestationsSpy).toHaveBeenCalledWith(SlotNumber(2));
284
+ expect(deleteAttestationsSpy).toHaveBeenCalledWith(SlotNumber(3));
285
+ expect(deleteAttestationsSpy).toHaveBeenCalledWith(SlotNumber(69));
286
+ expect(deleteAttestationsSpy).toHaveBeenCalledWith(SlotNumber(72));
274
287
  });
275
288
 
276
289
  describe('BlockProposal in attestation pool', () => {
@@ -334,7 +347,7 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
334
347
  const retrievedProposal = await ap.getBlockProposal(proposalId);
335
348
  expect(retrievedProposal).toBeDefined();
336
349
  expect(retrievedProposal!.toBuffer()).toEqual(proposal2.toBuffer());
337
- expect(retrievedProposal!.slotNumber.toBigInt()).toBe(BigInt(200));
350
+ expect(retrievedProposal!.slotNumber).toBe(SlotNumber(200));
338
351
  });
339
352
 
340
353
  it('should delete block proposal when deleting attestations for slot and proposal', async () => {
@@ -354,7 +367,7 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
354
367
  expect(await ap.hasBlockProposal(proposalId)).toBe(true);
355
368
 
356
369
  // Delete attestations for slot and proposal
357
- await ap.deleteAttestationsForSlotAndProposal(BigInt(slotNumber), proposalId);
370
+ await ap.deleteAttestationsForSlotAndProposal(SlotNumber(slotNumber), proposalId);
358
371
 
359
372
  // Proposal should be deleted
360
373
  retrievedProposal = await ap.getBlockProposal(proposalId);
@@ -377,7 +390,7 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
377
390
  expect(await ap.hasBlockProposal(proposal)).toBe(true);
378
391
 
379
392
  // Delete attestations for slot
380
- await ap.deleteAttestationsForSlot(BigInt(slotNumber));
393
+ await ap.deleteAttestationsForSlot(SlotNumber(slotNumber));
381
394
 
382
395
  // Proposal should be deleted
383
396
  retrievedProposal = await ap.getBlockProposal(proposalId);
@@ -400,7 +413,7 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
400
413
 
401
414
  // Retrieve both proposal and attestations
402
415
  const retrievedProposal = await ap.getBlockProposal(proposalId);
403
- const retrievedAttestations = await ap.getAttestationsForSlotAndProposal(BigInt(slotNumber), proposalId);
416
+ const retrievedAttestations = await ap.getAttestationsForSlotAndProposal(SlotNumber(slotNumber), proposalId);
404
417
 
405
418
  expect(retrievedProposal).toBeDefined();
406
419
  expect(retrievedProposal).toEqual(proposal);
@@ -1,3 +1,4 @@
1
+ import { SlotNumber } from '@aztec/foundation/branded-types';
1
2
  import { Fr } from '@aztec/foundation/fields';
2
3
  import { toArray } from '@aztec/foundation/iterable';
3
4
  import { createLogger } from '@aztec/foundation/log';
@@ -5,9 +6,13 @@ import type { AztecAsyncKVStore, AztecAsyncMap, AztecAsyncMultiMap } from '@azte
5
6
  import { BlockAttestation, BlockProposal } from '@aztec/stdlib/p2p';
6
7
  import { type TelemetryClient, getTelemetryClient } from '@aztec/telemetry-client';
7
8
 
9
+ import { ProposalSlotCapExceededError } from '../../errors/attestation-pool.error.js';
8
10
  import { PoolInstrumentation, PoolName, type PoolStatsCallback } from '../instrumentation.js';
9
11
  import type { AttestationPool } from './attestation_pool.js';
10
12
 
13
+ export const MAX_PROPOSALS_PER_SLOT = 5;
14
+ export const ATTESTATION_CAP_BUFFER = 10;
15
+
11
16
  export class KvAttestationPool implements AttestationPool {
12
17
  private metrics: PoolInstrumentation<BlockAttestation>;
13
18
 
@@ -16,7 +21,7 @@ export class KvAttestationPool implements AttestationPool {
16
21
  /* proposal.payload.archive */ string,
17
22
  /* buffer representation of proposal */ Buffer
18
23
  >;
19
- private proposalsForSlot: AztecAsyncMultiMap<string, string>;
24
+ private proposalsForSlot: AztecAsyncMultiMap<number, string>;
20
25
  private attestationsForProposal: AztecAsyncMultiMap<string, string>;
21
26
 
22
27
  constructor(
@@ -70,7 +75,7 @@ export class KvAttestationPool implements AttestationPool {
70
75
 
71
76
  // Skip attestations with invalid signatures
72
77
  if (!sender) {
73
- this.log.warn(`Skipping attestation with invalid signature for slot ${slotNumber.toBigInt()}`, {
78
+ this.log.warn(`Skipping attestation with invalid signature for slot ${slotNumber}`, {
74
79
  signature: attestation.signature.toString(),
75
80
  slotNumber,
76
81
  proposalId,
@@ -82,13 +87,13 @@ export class KvAttestationPool implements AttestationPool {
82
87
 
83
88
  await this.attestations.set(this.getAttestationKey(slotNumber, proposalId, address), attestation.toBuffer());
84
89
 
85
- await this.proposalsForSlot.set(slotNumber.toString(), proposalId.toString());
90
+ await this.proposalsForSlot.set(slotNumber, proposalId.toString());
86
91
  await this.attestationsForProposal.set(
87
92
  this.getProposalKey(slotNumber, proposalId),
88
93
  this.getAttestationKey(slotNumber, proposalId, address),
89
94
  );
90
95
 
91
- this.log.verbose(`Added attestation for slot ${slotNumber.toBigInt()} from ${address}`, {
96
+ this.log.verbose(`Added attestation for slot ${slotNumber} from ${address}`, {
92
97
  signature: attestation.signature.toString(),
93
98
  slotNumber,
94
99
  address,
@@ -98,9 +103,8 @@ export class KvAttestationPool implements AttestationPool {
98
103
  });
99
104
  }
100
105
 
101
- public async getAttestationsForSlot(slot: bigint): Promise<BlockAttestation[]> {
102
- const slotFr = new Fr(slot);
103
- const proposalIds = await toArray(this.proposalsForSlot.getValuesAsync(slotFr.toString()));
106
+ public async getAttestationsForSlot(slot: SlotNumber): Promise<BlockAttestation[]> {
107
+ const proposalIds = await toArray(this.proposalsForSlot.getValuesAsync(slot));
104
108
  const attestations: BlockAttestation[] = [];
105
109
 
106
110
  for (const proposalId of proposalIds) {
@@ -110,7 +114,7 @@ export class KvAttestationPool implements AttestationPool {
110
114
  return attestations;
111
115
  }
112
116
 
113
- public async getAttestationsForSlotAndProposal(slot: bigint, proposalId: string): Promise<BlockAttestation[]> {
117
+ public async getAttestationsForSlotAndProposal(slot: SlotNumber, proposalId: string): Promise<BlockAttestation[]> {
114
118
  const attestationIds = await toArray(
115
119
  this.attestationsForProposal.getValuesAsync(this.getProposalKey(slot, proposalId)),
116
120
  );
@@ -132,21 +136,20 @@ export class KvAttestationPool implements AttestationPool {
132
136
  return attestations;
133
137
  }
134
138
 
135
- public async deleteAttestationsOlderThan(oldestSlot: bigint): Promise<void> {
136
- const olderThan = await toArray(this.proposalsForSlot.keysAsync({ end: new Fr(oldestSlot).toString() }));
139
+ public async deleteAttestationsOlderThan(oldestSlot: SlotNumber): Promise<void> {
140
+ const olderThan = await toArray(this.proposalsForSlot.keysAsync({ end: oldestSlot }));
137
141
  for (const oldSlot of olderThan) {
138
- await this.deleteAttestationsForSlot(BigInt(oldSlot));
142
+ await this.deleteAttestationsForSlot(SlotNumber(oldSlot));
139
143
  }
140
144
  }
141
145
 
142
- public async deleteAttestationsForSlot(slot: bigint): Promise<void> {
143
- const slotFr = new Fr(slot);
146
+ public async deleteAttestationsForSlot(slot: SlotNumber): Promise<void> {
144
147
  let numberOfAttestations = 0;
145
148
  await this.store.transactionAsync(async () => {
146
- const proposalIds = await toArray(this.proposalsForSlot.getValuesAsync(slotFr.toString()));
149
+ const proposalIds = await toArray(this.proposalsForSlot.getValuesAsync(slot));
147
150
  for (const proposalId of proposalIds) {
148
151
  const attestations = await toArray(
149
- this.attestationsForProposal.getValuesAsync(this.getProposalKey(slotFr, proposalId)),
152
+ this.attestationsForProposal.getValuesAsync(this.getProposalKey(slot, proposalId)),
150
153
  );
151
154
 
152
155
  numberOfAttestations += attestations.length;
@@ -155,17 +158,19 @@ export class KvAttestationPool implements AttestationPool {
155
158
  }
156
159
 
157
160
  await this.proposals.delete(proposalId);
158
- await this.attestationsForProposal.delete(this.getProposalKey(slotFr, proposalId));
161
+ await this.attestationsForProposal.delete(this.getProposalKey(slot, proposalId));
159
162
  }
160
163
 
164
+ // Delete from proposalsForSlot
165
+ await this.proposalsForSlot.delete(slot);
166
+
161
167
  this.log.verbose(`Removed ${numberOfAttestations} attestations for slot ${slot}`);
162
168
  });
163
169
  }
164
170
 
165
- public async deleteAttestationsForSlotAndProposal(slot: bigint, proposalId: string): Promise<void> {
171
+ public async deleteAttestationsForSlotAndProposal(slot: SlotNumber, proposalId: string): Promise<void> {
166
172
  let numberOfAttestations = 0;
167
173
  await this.store.transactionAsync(async () => {
168
- const slotString = new Fr(slot).toString();
169
174
  const attestations = await toArray(
170
175
  this.attestationsForProposal.getValuesAsync(this.getProposalKey(slot, proposalId)),
171
176
  );
@@ -176,8 +181,8 @@ export class KvAttestationPool implements AttestationPool {
176
181
  }
177
182
 
178
183
  await this.proposals.delete(proposalId);
179
- await this.proposalsForSlot.deleteValue(slotString, proposalId);
180
- await this.attestationsForProposal.delete(this.getProposalKey(slotString, proposalId));
184
+ await this.proposalsForSlot.deleteValue(slot, proposalId);
185
+ await this.attestationsForProposal.delete(this.getProposalKey(slot, proposalId));
181
186
 
182
187
  this.log.verbose(`Removed ${numberOfAttestations} attestations for slot ${slot} and proposal ${proposalId}`);
183
188
  });
@@ -192,7 +197,7 @@ export class KvAttestationPool implements AttestationPool {
192
197
 
193
198
  // Skip attestations with invalid signatures
194
199
  if (!sender) {
195
- this.log.warn(`Skipping deletion of attestation with invalid signature for slot ${slotNumber.toBigInt()}`);
200
+ this.log.warn(`Skipping deletion of attestation with invalid signature for slot ${slotNumber}`);
196
201
  continue;
197
202
  }
198
203
 
@@ -249,8 +254,45 @@ export class KvAttestationPool implements AttestationPool {
249
254
 
250
255
  public async addBlockProposal(blockProposal: BlockProposal): Promise<void> {
251
256
  await this.store.transactionAsync(async () => {
252
- await this.proposalsForSlot.set(blockProposal.slotNumber.toString(), blockProposal.archive.toString());
253
- await this.proposals.set(blockProposal.payload.archive.toString(), blockProposal.toBuffer());
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());
254
269
  });
255
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
+ return (
284
+ (await this.proposals.hasAsync(block.archive.toString())) || !(await this.hasReachedProposalCap(block.slotNumber))
285
+ );
286
+ }
287
+
288
+ public async canAddAttestation(attestation: BlockAttestation, committeeSize: number): Promise<boolean> {
289
+ return (
290
+ (await this.hasAttestation(attestation)) ||
291
+ !(await this.hasReachedAttestationCap(
292
+ attestation.payload.header.slotNumber,
293
+ attestation.archive.toString(),
294
+ committeeSize,
295
+ ))
296
+ );
297
+ }
256
298
  }
@@ -1,14 +1,20 @@
1
+ import type { SlotNumber } from '@aztec/foundation/branded-types';
1
2
  import { createLogger } from '@aztec/foundation/log';
2
3
  import type { BlockAttestation, BlockProposal } from '@aztec/stdlib/p2p';
3
4
  import { type TelemetryClient, getTelemetryClient } from '@aztec/telemetry-client';
4
5
 
5
6
  import { PoolInstrumentation, PoolName, type PoolStatsCallback } from '../instrumentation.js';
6
7
  import type { AttestationPool } from './attestation_pool.js';
8
+ import { ATTESTATION_CAP_BUFFER, MAX_PROPOSALS_PER_SLOT } from './kv_attestation_pool.js';
7
9
 
8
10
  export class InMemoryAttestationPool implements AttestationPool {
9
11
  private metrics: PoolInstrumentation<BlockAttestation>;
10
12
 
11
- private attestations: Map</*slot=*/ bigint, Map</*proposalId*/ string, Map</*address=*/ string, BlockAttestation>>>;
13
+ // eslint-disable-next-line aztec-custom/no-non-primitive-in-collections
14
+ private attestations: Map<
15
+ /*slot=*/ SlotNumber,
16
+ Map</*proposalId*/ string, Map</*address=*/ string, BlockAttestation>>
17
+ >;
12
18
  private proposals: Map<string, BlockProposal>;
13
19
 
14
20
  constructor(
@@ -30,7 +36,7 @@ export class InMemoryAttestationPool implements AttestationPool {
30
36
  return Promise.resolve(this.attestations.size === 0);
31
37
  }
32
38
 
33
- public getAttestationsForSlot(slot: bigint): Promise<BlockAttestation[]> {
39
+ public getAttestationsForSlot(slot: SlotNumber): Promise<BlockAttestation[]> {
34
40
  return Promise.resolve(
35
41
  Array.from(this.attestations.get(slot)?.values() ?? []).flatMap(proposalAttestationMap =>
36
42
  Array.from(proposalAttestationMap.values()),
@@ -38,7 +44,7 @@ export class InMemoryAttestationPool implements AttestationPool {
38
44
  );
39
45
  }
40
46
 
41
- public getAttestationsForSlotAndProposal(slot: bigint, proposalId: string): Promise<BlockAttestation[]> {
47
+ public getAttestationsForSlotAndProposal(slot: SlotNumber, proposalId: string): Promise<BlockAttestation[]> {
42
48
  const slotAttestationMap = this.attestations.get(slot);
43
49
  if (slotAttestationMap) {
44
50
  const proposalAttestationMap = slotAttestationMap.get(proposalId);
@@ -59,7 +65,7 @@ export class InMemoryAttestationPool implements AttestationPool {
59
65
 
60
66
  // Skip attestations with invalid signatures
61
67
  if (!sender) {
62
- this.log.warn(`Skipping attestation with invalid signature for slot ${slotNumber.toBigInt()}`, {
68
+ this.log.warn(`Skipping attestation with invalid signature for slot ${slotNumber}`, {
63
69
  signature: attestation.signature.toString(),
64
70
  slotNumber,
65
71
  proposalId,
@@ -67,11 +73,11 @@ export class InMemoryAttestationPool implements AttestationPool {
67
73
  continue;
68
74
  }
69
75
 
70
- const slotAttestationMap = getSlotOrDefault(this.attestations, slotNumber.toBigInt());
76
+ const slotAttestationMap = getSlotOrDefault(this.attestations, slotNumber);
71
77
  const proposalAttestationMap = getProposalOrDefault(slotAttestationMap, proposalId);
72
78
  proposalAttestationMap.set(sender.toString(), attestation);
73
79
 
74
- this.log.verbose(`Added attestation for slot ${slotNumber.toBigInt()} from ${sender}`, {
80
+ this.log.verbose(`Added attestation for slot ${slotNumber} from ${sender}`, {
75
81
  signature: attestation.signature.toString(),
76
82
  slotNumber,
77
83
  address: sender,
@@ -82,7 +88,7 @@ export class InMemoryAttestationPool implements AttestationPool {
82
88
  return Promise.resolve();
83
89
  }
84
90
 
85
- #getNumberOfAttestationsInSlot(slot: bigint): number {
91
+ #getNumberOfAttestationsInSlot(slot: SlotNumber): number {
86
92
  let total = 0;
87
93
  const slotAttestationMap = getSlotOrDefault(this.attestations, slot);
88
94
 
@@ -94,7 +100,7 @@ export class InMemoryAttestationPool implements AttestationPool {
94
100
  return total;
95
101
  }
96
102
 
97
- public async deleteAttestationsOlderThan(oldestSlot: bigint): Promise<void> {
103
+ public async deleteAttestationsOlderThan(oldestSlot: SlotNumber): Promise<void> {
98
104
  const olderThan = [];
99
105
 
100
106
  // Entries are iterated in insertion order, so we can break as soon as we find a slot that is older than the oldestSlot.
@@ -115,7 +121,7 @@ export class InMemoryAttestationPool implements AttestationPool {
115
121
  return Promise.resolve();
116
122
  }
117
123
 
118
- public deleteAttestationsForSlot(slot: bigint): Promise<void> {
124
+ public deleteAttestationsForSlot(slot: SlotNumber): Promise<void> {
119
125
  // We count the number of attestations we are removing
120
126
  const numberOfAttestations = this.#getNumberOfAttestationsInSlot(slot);
121
127
  const proposalIdsToDelete = this.attestations.get(slot)?.keys();
@@ -133,7 +139,7 @@ export class InMemoryAttestationPool implements AttestationPool {
133
139
  return Promise.resolve();
134
140
  }
135
141
 
136
- public deleteAttestationsForSlotAndProposal(slot: bigint, proposalId: string): Promise<void> {
142
+ public deleteAttestationsForSlotAndProposal(slot: SlotNumber, proposalId: string): Promise<void> {
137
143
  const slotAttestationMap = getSlotOrDefault(this.attestations, slot);
138
144
  if (slotAttestationMap) {
139
145
  if (slotAttestationMap.has(proposalId)) {
@@ -152,7 +158,7 @@ export class InMemoryAttestationPool implements AttestationPool {
152
158
  public deleteAttestations(attestations: BlockAttestation[]): Promise<void> {
153
159
  for (const attestation of attestations) {
154
160
  const slotNumber = attestation.payload.header.slotNumber;
155
- const slotAttestationMap = this.attestations.get(slotNumber.toBigInt());
161
+ const slotAttestationMap = this.attestations.get(slotNumber);
156
162
  if (slotAttestationMap) {
157
163
  const proposalId = attestation.archive.toString();
158
164
  const proposalAttestationMap = getProposalOrDefault(slotAttestationMap, proposalId);
@@ -161,7 +167,7 @@ export class InMemoryAttestationPool implements AttestationPool {
161
167
 
162
168
  // Skip attestations with invalid signatures
163
169
  if (!sender) {
164
- this.log.warn(`Skipping deletion of attestation with invalid signature for slot ${slotNumber.toBigInt()}`);
170
+ this.log.warn(`Skipping deletion of attestation with invalid signature for slot ${slotNumber}`);
165
171
  continue;
166
172
  }
167
173
 
@@ -183,7 +189,7 @@ export class InMemoryAttestationPool implements AttestationPool {
183
189
  return Promise.resolve(false);
184
190
  }
185
191
 
186
- const slotAttestationMap = this.attestations.get(slotNumber.toBigInt());
192
+ const slotAttestationMap = this.attestations.get(slotNumber);
187
193
  if (!slotAttestationMap) {
188
194
  return Promise.resolve(false);
189
195
  }
@@ -199,7 +205,7 @@ export class InMemoryAttestationPool implements AttestationPool {
199
205
  public addBlockProposal(blockProposal: BlockProposal): Promise<void> {
200
206
  // We initialize slot-proposal mapping if it does not exist
201
207
  // This is important to ensure we can delete this proposal if there were not attestations for it
202
- const slotProposalMapping = getSlotOrDefault(this.attestations, blockProposal.slotNumber.toBigInt());
208
+ const slotProposalMapping = getSlotOrDefault(this.attestations, blockProposal.slotNumber);
203
209
  slotProposalMapping.set(blockProposal.payload.archive.toString(), new Map<string, BlockAttestation>());
204
210
 
205
211
  this.proposals.set(blockProposal.payload.archive.toString(), blockProposal);
@@ -214,6 +220,33 @@ export class InMemoryAttestationPool implements AttestationPool {
214
220
  const id = typeof idOrProposal === 'string' ? idOrProposal : idOrProposal.payload.archive.toString();
215
221
  return Promise.resolve(this.proposals.has(id));
216
222
  }
223
+
224
+ public hasReachedProposalCap(slot: SlotNumber): Promise<boolean> {
225
+ const slotAttestationMap = this.attestations.get(slot);
226
+ const proposalCount = slotAttestationMap?.size ?? 0;
227
+ return Promise.resolve(proposalCount >= MAX_PROPOSALS_PER_SLOT);
228
+ }
229
+
230
+ public hasReachedAttestationCap(slot: SlotNumber, proposalId: string, committeeSize: number): Promise<boolean> {
231
+ const limit = committeeSize + ATTESTATION_CAP_BUFFER;
232
+ const count = this.attestations.get(slot)?.get(proposalId)?.size ?? 0;
233
+ return Promise.resolve(limit <= 0 || count >= limit);
234
+ }
235
+
236
+ public async canAddProposal(block: BlockProposal): Promise<boolean> {
237
+ return this.proposals.has(block.archive.toString()) || !(await this.hasReachedProposalCap(block.slotNumber));
238
+ }
239
+
240
+ public async canAddAttestation(attestation: BlockAttestation, committeeSize: number): Promise<boolean> {
241
+ const sender = attestation.getSender();
242
+ const slot = attestation.payload.header.slotNumber;
243
+ const pid = attestation.archive.toString();
244
+ return (
245
+ !!sender &&
246
+ ((this.attestations.get(slot)?.get(pid)?.has(sender.toString()) ?? false) ||
247
+ !(await this.hasReachedAttestationCap(slot, pid, committeeSize)))
248
+ );
249
+ }
217
250
  }
218
251
 
219
252
  /**
@@ -225,8 +258,9 @@ export class InMemoryAttestationPool implements AttestationPool {
225
258
  * @returns The slot mapping
226
259
  */
227
260
  function getSlotOrDefault(
228
- map: Map<bigint, Map<string, Map<string, BlockAttestation>>>,
229
- slot: bigint,
261
+ // eslint-disable-next-line aztec-custom/no-non-primitive-in-collections
262
+ map: Map<SlotNumber, Map<string, Map<string, BlockAttestation>>>,
263
+ slot: SlotNumber,
230
264
  ): Map<string, Map<string, BlockAttestation>> {
231
265
  if (!map.has(slot)) {
232
266
  map.set(slot, new Map<string, Map<string, BlockAttestation>>());
@@ -33,7 +33,7 @@ export const mockAttestation = (
33
33
  ): BlockAttestation => {
34
34
  // Use arbitrary numbers for all other than slot
35
35
  const header = makeL2BlockHeader(1, 2, slot);
36
- const payload = new ConsensusPayload(header.toCheckpointHeader(), archive, header.state);
36
+ const payload = new ConsensusPayload(header.toCheckpointHeader(), archive);
37
37
 
38
38
  const attestationHash = getHashedSignaturePayloadEthSignedMessage(payload, SignatureDomainSeparator.blockAttestation);
39
39
  const attestationSignature = signer.sign(attestationHash);
@@ -10,6 +10,7 @@ import {
10
10
  type MetricsType,
11
11
  type ObservableGauge,
12
12
  type TelemetryClient,
13
+ type UpDownCounter,
13
14
  } from '@aztec/telemetry-client';
14
15
 
15
16
  export enum PoolName {
@@ -20,6 +21,7 @@ export enum PoolName {
20
21
  type MetricsLabels = {
21
22
  objectInMempool: MetricsType;
22
23
  objectSize: MetricsType;
24
+ itemsAdded: MetricsType;
23
25
  };
24
26
 
25
27
  /**
@@ -32,11 +34,13 @@ function getMetricsLabels(name: PoolName): MetricsLabels {
32
34
  return {
33
35
  objectInMempool: Metrics.MEMPOOL_TX_COUNT,
34
36
  objectSize: Metrics.MEMPOOL_TX_SIZE,
37
+ itemsAdded: Metrics.MEMPOOL_TX_ADDED_COUNT,
35
38
  };
36
39
  } else if (name === PoolName.ATTESTATION_POOL) {
37
40
  return {
38
41
  objectInMempool: Metrics.MEMPOOL_ATTESTATIONS_COUNT,
39
42
  objectSize: Metrics.MEMPOOL_ATTESTATIONS_SIZE,
43
+ itemsAdded: Metrics.MEMPOOL_ATTESTATIONS_ADDED_COUNT,
40
44
  };
41
45
  }
42
46
 
@@ -53,6 +57,7 @@ export type PoolStatsCallback = () => Promise<{
53
57
  export class PoolInstrumentation<PoolObject extends Gossipable> {
54
58
  /** The number of txs in the mempool */
55
59
  private objectsInMempool: ObservableGauge;
60
+ private addObjectCounter: UpDownCounter;
56
61
  /** Tracks tx size */
57
62
  private objectSize: Histogram;
58
63
 
@@ -89,6 +94,10 @@ export class PoolInstrumentation<PoolObject extends Gossipable> {
89
94
  dbStats,
90
95
  );
91
96
 
97
+ this.addObjectCounter = this.meter.createUpDownCounter(metricsLabels.itemsAdded, {
98
+ description: 'The number of transactions added to the mempool',
99
+ });
100
+
92
101
  this.meter.addBatchObservableCallback(this.observeStats, [this.objectsInMempool]);
93
102
  }
94
103
 
@@ -96,6 +105,10 @@ export class PoolInstrumentation<PoolObject extends Gossipable> {
96
105
  this.objectSize.record(poolObject.getSize());
97
106
  }
98
107
 
108
+ public incrementAddedObjects(count: number) {
109
+ this.addObjectCounter.add(count);
110
+ }
111
+
99
112
  private observeStats = async (observer: BatchObservableResult) => {
100
113
  const { itemCount } = await this.poolStats();
101
114
  if (typeof itemCount === 'number') {