@aztec/p2p 0.67.1 → 0.68.1

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 (211) hide show
  1. package/dest/bootstrap/bootstrap.d.ts +5 -3
  2. package/dest/bootstrap/bootstrap.d.ts.map +1 -1
  3. package/dest/bootstrap/bootstrap.js +17 -15
  4. package/dest/client/factory.d.ts +19 -0
  5. package/dest/client/factory.d.ts.map +1 -0
  6. package/dest/client/factory.js +40 -0
  7. package/dest/client/index.d.ts +1 -15
  8. package/dest/client/index.d.ts.map +1 -1
  9. package/dest/client/index.js +2 -37
  10. package/dest/client/p2p_client.d.ts +6 -6
  11. package/dest/client/p2p_client.d.ts.map +1 -1
  12. package/dest/client/p2p_client.js +12 -11
  13. package/dest/config.d.ts +1 -1
  14. package/dest/config.d.ts.map +1 -1
  15. package/dest/config.js +3 -3
  16. package/dest/errors/reqresp.error.d.ts +12 -1
  17. package/dest/errors/reqresp.error.d.ts.map +1 -1
  18. package/dest/errors/reqresp.error.js +15 -2
  19. package/dest/index.d.ts +2 -2
  20. package/dest/index.d.ts.map +1 -1
  21. package/dest/index.js +3 -3
  22. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +9 -0
  23. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
  24. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts +3 -0
  25. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts.map +1 -0
  26. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.js +171 -0
  27. package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts +29 -0
  28. package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts.map +1 -0
  29. package/dest/mem_pools/attestation_pool/kv_attestation_pool.js +114 -0
  30. package/dest/mem_pools/interface.d.ts +4 -3
  31. package/dest/mem_pools/interface.d.ts.map +1 -1
  32. package/dest/mocks/index.d.ts +7 -6
  33. package/dest/mocks/index.d.ts.map +1 -1
  34. package/dest/mocks/index.js +8 -8
  35. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +8 -0
  36. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -0
  37. package/dest/msg_validators/attestation_validator/attestation_validator.js +19 -0
  38. package/dest/msg_validators/attestation_validator/index.d.ts +2 -0
  39. package/dest/msg_validators/attestation_validator/index.d.ts.map +1 -0
  40. package/dest/msg_validators/attestation_validator/index.js +2 -0
  41. package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts +8 -0
  42. package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts.map +1 -0
  43. package/dest/msg_validators/block_proposal_validator/block_proposal_validator.js +21 -0
  44. package/dest/msg_validators/block_proposal_validator/index.d.ts +2 -0
  45. package/dest/msg_validators/block_proposal_validator/index.d.ts.map +1 -0
  46. package/dest/msg_validators/block_proposal_validator/index.js +2 -0
  47. package/dest/msg_validators/epoch_proof_quote_validator/epoch_proof_quote_validator.d.ts +8 -0
  48. package/dest/msg_validators/epoch_proof_quote_validator/epoch_proof_quote_validator.d.ts.map +1 -0
  49. package/dest/msg_validators/epoch_proof_quote_validator/epoch_proof_quote_validator.js +16 -0
  50. package/dest/msg_validators/epoch_proof_quote_validator/index.d.ts +2 -0
  51. package/dest/msg_validators/epoch_proof_quote_validator/index.d.ts.map +1 -0
  52. package/dest/msg_validators/epoch_proof_quote_validator/index.js +2 -0
  53. package/dest/msg_validators/index.d.ts +4 -0
  54. package/dest/msg_validators/index.d.ts.map +1 -0
  55. package/dest/msg_validators/index.js +4 -0
  56. package/dest/{tx_validator → msg_validators/tx_validator}/aggregate_tx_validator.d.ts +1 -1
  57. package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts.map +1 -0
  58. package/dest/msg_validators/tx_validator/aggregate_tx_validator.js +34 -0
  59. package/dest/msg_validators/tx_validator/data_validator.d.ts.map +1 -0
  60. package/dest/{tx_validator → msg_validators/tx_validator}/data_validator.js +1 -1
  61. package/dest/{tx_validator → msg_validators/tx_validator}/double_spend_validator.d.ts +3 -2
  62. package/dest/msg_validators/tx_validator/double_spend_validator.d.ts.map +1 -0
  63. package/dest/msg_validators/tx_validator/double_spend_validator.js +56 -0
  64. package/dest/msg_validators/tx_validator/index.d.ts.map +1 -0
  65. package/dest/{tx_validator → msg_validators/tx_validator}/index.js +1 -1
  66. package/dest/msg_validators/tx_validator/metadata_validator.d.ts.map +1 -0
  67. package/dest/{tx_validator → msg_validators/tx_validator}/metadata_validator.js +1 -1
  68. package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts.map +1 -0
  69. package/dest/msg_validators/tx_validator/tx_proof_validator.js +29 -0
  70. package/dest/services/data_store.d.ts.map +1 -0
  71. package/dest/services/data_store.js +188 -0
  72. package/dest/{service → services/discv5}/discV5_service.d.ts +3 -9
  73. package/dest/services/discv5/discV5_service.d.ts.map +1 -0
  74. package/dest/services/discv5/discV5_service.js +139 -0
  75. package/dest/services/dummy_service.d.ts.map +1 -0
  76. package/dest/{service → services}/dummy_service.js +1 -1
  77. package/dest/{service → services}/encoding.d.ts +5 -0
  78. package/dest/services/encoding.d.ts.map +1 -0
  79. package/dest/services/encoding.js +65 -0
  80. package/dest/services/index.d.ts +3 -0
  81. package/dest/services/index.d.ts.map +1 -0
  82. package/dest/services/index.js +3 -0
  83. package/dest/services/libp2p/libp2p_service.d.ts +222 -0
  84. package/dest/services/libp2p/libp2p_service.d.ts.map +1 -0
  85. package/dest/services/libp2p/libp2p_service.js +697 -0
  86. package/dest/services/peer-scoring/peer_scoring.d.ts +25 -0
  87. package/dest/services/peer-scoring/peer_scoring.d.ts.map +1 -0
  88. package/dest/services/peer-scoring/peer_scoring.js +75 -0
  89. package/dest/services/peer_manager.d.ts +60 -0
  90. package/dest/services/peer_manager.d.ts.map +1 -0
  91. package/dest/services/peer_manager.js +358 -0
  92. package/dest/services/reqresp/config.d.ts.map +1 -0
  93. package/dest/{service → services}/reqresp/config.js +1 -1
  94. package/dest/services/reqresp/handlers.d.ts.map +1 -0
  95. package/dest/{service → services}/reqresp/handlers.js +1 -1
  96. package/dest/services/reqresp/index.d.ts.map +1 -0
  97. package/dest/{service → services}/reqresp/index.js +1 -1
  98. package/dest/services/reqresp/interface.d.ts.map +1 -0
  99. package/dest/{service → services}/reqresp/interface.js +1 -1
  100. package/dest/services/reqresp/rate_limiter/index.d.ts.map +1 -0
  101. package/dest/{service → services}/reqresp/rate_limiter/index.js +1 -1
  102. package/dest/{service → services}/reqresp/rate_limiter/rate_limiter.d.ts +0 -5
  103. package/dest/services/reqresp/rate_limiter/rate_limiter.d.ts.map +1 -0
  104. package/dest/{service → services}/reqresp/rate_limiter/rate_limiter.js +7 -2
  105. package/dest/services/reqresp/rate_limiter/rate_limits.d.ts.map +1 -0
  106. package/dest/{service → services}/reqresp/rate_limiter/rate_limits.js +1 -1
  107. package/dest/{service → services}/reqresp/reqresp.d.ts +16 -0
  108. package/dest/services/reqresp/reqresp.d.ts.map +1 -0
  109. package/dest/services/reqresp/reqresp.js +279 -0
  110. package/dest/services/service.d.ts.map +1 -0
  111. package/dest/{service → services}/service.js +1 -1
  112. package/dest/services/types.d.ts +38 -0
  113. package/dest/services/types.d.ts.map +1 -0
  114. package/dest/services/types.js +43 -0
  115. package/package.json +14 -11
  116. package/src/bootstrap/bootstrap.ts +25 -20
  117. package/src/client/factory.ts +97 -0
  118. package/src/client/index.ts +1 -73
  119. package/src/client/p2p_client.ts +28 -15
  120. package/src/config.ts +2 -2
  121. package/src/errors/reqresp.error.ts +15 -1
  122. package/src/index.ts +2 -2
  123. package/src/mem_pools/attestation_pool/attestation_pool.ts +10 -0
  124. package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +237 -0
  125. package/src/mem_pools/attestation_pool/kv_attestation_pool.ts +153 -0
  126. package/src/mem_pools/interface.ts +5 -3
  127. package/src/mocks/index.ts +16 -10
  128. package/src/msg_validators/attestation_validator/attestation_validator.ts +26 -0
  129. package/src/msg_validators/attestation_validator/index.ts +1 -0
  130. package/src/msg_validators/block_proposal_validator/block_proposal_validator.ts +29 -0
  131. package/src/msg_validators/block_proposal_validator/index.ts +1 -0
  132. package/src/msg_validators/epoch_proof_quote_validator/epoch_proof_quote_validator.ts +22 -0
  133. package/src/msg_validators/epoch_proof_quote_validator/index.ts +1 -0
  134. package/src/msg_validators/index.ts +3 -0
  135. package/src/{tx_validator → msg_validators/tx_validator}/aggregate_tx_validator.ts +5 -3
  136. package/src/{tx_validator → msg_validators/tx_validator}/double_spend_validator.ts +6 -8
  137. package/src/{service → services/discv5}/discV5_service.ts +19 -23
  138. package/src/{service → services}/encoding.ts +21 -3
  139. package/src/services/index.ts +2 -0
  140. package/src/{service → services/libp2p}/libp2p_service.ts +350 -90
  141. package/src/{service → services/peer-scoring}/peer_scoring.ts +27 -23
  142. package/src/services/peer_manager.ts +422 -0
  143. package/src/{service → services}/reqresp/rate_limiter/rate_limiter.ts +2 -1
  144. package/src/{service → services}/reqresp/reqresp.ts +86 -20
  145. package/src/services/types.ts +44 -0
  146. package/dest/service/data_store.d.ts.map +0 -1
  147. package/dest/service/data_store.js +0 -188
  148. package/dest/service/discV5_service.d.ts.map +0 -1
  149. package/dest/service/discV5_service.js +0 -144
  150. package/dest/service/dummy_service.d.ts.map +0 -1
  151. package/dest/service/encoding.d.ts.map +0 -1
  152. package/dest/service/encoding.js +0 -49
  153. package/dest/service/index.d.ts +0 -3
  154. package/dest/service/index.d.ts.map +0 -1
  155. package/dest/service/index.js +0 -3
  156. package/dest/service/libp2p_service.d.ts +0 -136
  157. package/dest/service/libp2p_service.d.ts.map +0 -1
  158. package/dest/service/libp2p_service.js +0 -500
  159. package/dest/service/peer_manager.d.ts +0 -33
  160. package/dest/service/peer_manager.d.ts.map +0 -1
  161. package/dest/service/peer_manager.js +0 -214
  162. package/dest/service/peer_scoring.d.ts +0 -35
  163. package/dest/service/peer_scoring.d.ts.map +0 -1
  164. package/dest/service/peer_scoring.js +0 -72
  165. package/dest/service/reqresp/config.d.ts.map +0 -1
  166. package/dest/service/reqresp/handlers.d.ts.map +0 -1
  167. package/dest/service/reqresp/index.d.ts.map +0 -1
  168. package/dest/service/reqresp/interface.d.ts.map +0 -1
  169. package/dest/service/reqresp/rate_limiter/index.d.ts.map +0 -1
  170. package/dest/service/reqresp/rate_limiter/rate_limiter.d.ts.map +0 -1
  171. package/dest/service/reqresp/rate_limiter/rate_limits.d.ts.map +0 -1
  172. package/dest/service/reqresp/reqresp.d.ts.map +0 -1
  173. package/dest/service/reqresp/reqresp.js +0 -230
  174. package/dest/service/service.d.ts.map +0 -1
  175. package/dest/tx_validator/aggregate_tx_validator.d.ts.map +0 -1
  176. package/dest/tx_validator/aggregate_tx_validator.js +0 -32
  177. package/dest/tx_validator/data_validator.d.ts.map +0 -1
  178. package/dest/tx_validator/double_spend_validator.d.ts.map +0 -1
  179. package/dest/tx_validator/double_spend_validator.js +0 -56
  180. package/dest/tx_validator/index.d.ts.map +0 -1
  181. package/dest/tx_validator/metadata_validator.d.ts.map +0 -1
  182. package/dest/tx_validator/tx_proof_validator.d.ts.map +0 -1
  183. package/dest/tx_validator/tx_proof_validator.js +0 -29
  184. package/src/service/index.ts +0 -2
  185. package/src/service/peer_manager.ts +0 -266
  186. /package/dest/{tx_validator → msg_validators/tx_validator}/data_validator.d.ts +0 -0
  187. /package/dest/{tx_validator → msg_validators/tx_validator}/index.d.ts +0 -0
  188. /package/dest/{tx_validator → msg_validators/tx_validator}/metadata_validator.d.ts +0 -0
  189. /package/dest/{tx_validator → msg_validators/tx_validator}/tx_proof_validator.d.ts +0 -0
  190. /package/dest/{service → services}/data_store.d.ts +0 -0
  191. /package/dest/{service → services}/dummy_service.d.ts +0 -0
  192. /package/dest/{service → services}/reqresp/config.d.ts +0 -0
  193. /package/dest/{service → services}/reqresp/handlers.d.ts +0 -0
  194. /package/dest/{service → services}/reqresp/index.d.ts +0 -0
  195. /package/dest/{service → services}/reqresp/interface.d.ts +0 -0
  196. /package/dest/{service → services}/reqresp/rate_limiter/index.d.ts +0 -0
  197. /package/dest/{service → services}/reqresp/rate_limiter/rate_limits.d.ts +0 -0
  198. /package/dest/{service → services}/service.d.ts +0 -0
  199. /package/src/{tx_validator → msg_validators/tx_validator}/data_validator.ts +0 -0
  200. /package/src/{tx_validator → msg_validators/tx_validator}/index.ts +0 -0
  201. /package/src/{tx_validator → msg_validators/tx_validator}/metadata_validator.ts +0 -0
  202. /package/src/{tx_validator → msg_validators/tx_validator}/tx_proof_validator.ts +0 -0
  203. /package/src/{service → services}/data_store.ts +0 -0
  204. /package/src/{service → services}/dummy_service.ts +0 -0
  205. /package/src/{service → services}/reqresp/config.ts +0 -0
  206. /package/src/{service → services}/reqresp/handlers.ts +0 -0
  207. /package/src/{service → services}/reqresp/index.ts +0 -0
  208. /package/src/{service → services}/reqresp/interface.ts +0 -0
  209. /package/src/{service → services}/reqresp/rate_limiter/index.ts +0 -0
  210. /package/src/{service → services}/reqresp/rate_limiter/rate_limits.ts +0 -0
  211. /package/src/{service → services}/service.ts +0 -0
@@ -0,0 +1,153 @@
1
+ import { BlockAttestation } from '@aztec/circuit-types';
2
+ import { Fr } from '@aztec/foundation/fields';
3
+ import { createLogger } from '@aztec/foundation/log';
4
+ import { type AztecKVStore, type AztecMapWithSize, type AztecMultiMap } from '@aztec/kv-store';
5
+ import { type TelemetryClient } from '@aztec/telemetry-client';
6
+
7
+ import { PoolInstrumentation, PoolName } from '../instrumentation.js';
8
+ import { type AttestationPool } from './attestation_pool.js';
9
+
10
+ export class KvAttestationPool implements AttestationPool {
11
+ private metrics: PoolInstrumentation<BlockAttestation>;
12
+
13
+ // Index of all proposal ids in a slot
14
+ private attestations: AztecMultiMap<string, string>;
15
+
16
+ constructor(
17
+ private store: AztecKVStore,
18
+ telemetry: TelemetryClient,
19
+ private log = createLogger('aztec:attestation_pool'),
20
+ ) {
21
+ this.attestations = store.openMultiMap('attestations');
22
+ this.metrics = new PoolInstrumentation(telemetry, PoolName.ATTESTATION_POOL);
23
+ }
24
+
25
+ private getProposalMapKey(slot: string, proposalId: string): string {
26
+ return `proposal-${slot}-${proposalId}`;
27
+ }
28
+
29
+ /**
30
+ * Get the proposal map for a given slot and proposalId
31
+ *
32
+ * Essentially a nested mapping of address -> attestation
33
+ *
34
+ * @param slot - The slot to get the proposal map for
35
+ * @param proposalId - The proposalId to get the map for
36
+ * @returns The proposal map
37
+ */
38
+ private getProposalMap(slot: string, proposalId: string): AztecMapWithSize<string, Buffer> {
39
+ const mapKey = this.getProposalMapKey(slot, proposalId);
40
+ return this.store.openMapWithSize(mapKey);
41
+ }
42
+
43
+ public async addAttestations(attestations: BlockAttestation[]): Promise<void> {
44
+ for (const attestation of attestations) {
45
+ const slotNumber = attestation.payload.header.globalVariables.slotNumber.toString();
46
+ const proposalId = attestation.archive.toString();
47
+ const address = attestation.getSender().toString();
48
+
49
+ // Index the proposalId in the slot map
50
+ await this.attestations.set(slotNumber, proposalId);
51
+
52
+ // Store the actual attestation in the proposal map
53
+ const proposalMap = this.getProposalMap(slotNumber, proposalId);
54
+ await proposalMap.set(address, attestation.toBuffer());
55
+
56
+ this.log.verbose(`Added attestation for slot ${slotNumber} from ${address}`);
57
+ }
58
+
59
+ this.metrics.recordAddedObjects(attestations.length);
60
+ }
61
+
62
+ public getAttestationsForSlot(slot: bigint, proposalId: string): Promise<BlockAttestation[]> {
63
+ const slotNumber = new Fr(slot).toString();
64
+ const proposalMap = this.getProposalMap(slotNumber, proposalId);
65
+ const attestations = proposalMap.values();
66
+ const attestationsArray = Array.from(attestations).map(attestation => BlockAttestation.fromBuffer(attestation));
67
+ return Promise.resolve(attestationsArray);
68
+ }
69
+
70
+ public async deleteAttestationsOlderThan(oldestSlot: bigint): Promise<void> {
71
+ const olderThan = [];
72
+
73
+ const slots = this.attestations.keys();
74
+ for (const slot of slots) {
75
+ if (BigInt(slot) < oldestSlot) {
76
+ olderThan.push(slot);
77
+ }
78
+ }
79
+
80
+ await Promise.all(olderThan.map(oldSlot => this.deleteAttestationsForSlot(BigInt(oldSlot))));
81
+ return Promise.resolve();
82
+ }
83
+
84
+ public async deleteAttestationsForSlot(slot: bigint): Promise<void> {
85
+ const deletionPromises = [];
86
+
87
+ const slotString = new Fr(slot).toString();
88
+ let numberOfAttestations = 0;
89
+ const proposalIds = this.attestations.getValues(slotString);
90
+
91
+ if (proposalIds) {
92
+ for (const proposalId of proposalIds) {
93
+ const proposalMap = this.getProposalMap(slotString, proposalId);
94
+ numberOfAttestations += proposalMap.size();
95
+ deletionPromises.push(proposalMap.clear());
96
+ }
97
+ }
98
+
99
+ await Promise.all(deletionPromises);
100
+
101
+ this.log.verbose(`Removed ${numberOfAttestations} attestations for slot ${slot}`);
102
+ this.metrics.recordRemovedObjects(numberOfAttestations);
103
+ return Promise.resolve();
104
+ }
105
+
106
+ public async deleteAttestationsForSlotAndProposal(slot: bigint, proposalId: string): Promise<void> {
107
+ const deletionPromises = [];
108
+
109
+ const slotString = new Fr(slot).toString();
110
+ const exists = this.attestations.get(slotString);
111
+
112
+ if (exists) {
113
+ // Remove the proposalId from the slot index
114
+ deletionPromises.push(this.attestations.deleteValue(slotString, proposalId));
115
+
116
+ // Delete all attestations for the proposalId
117
+ const proposalMap = this.getProposalMap(slotString, proposalId);
118
+ const numberOfAttestations = proposalMap.size();
119
+ deletionPromises.push(proposalMap.clear());
120
+
121
+ this.log.verbose(`Removed ${numberOfAttestations} attestations for slot ${slot} and proposal ${proposalId}`);
122
+ this.metrics.recordRemovedObjects(numberOfAttestations);
123
+ }
124
+
125
+ await Promise.all(deletionPromises);
126
+ return Promise.resolve();
127
+ }
128
+
129
+ public async deleteAttestations(attestations: BlockAttestation[]): Promise<void> {
130
+ const deletionPromises = [];
131
+
132
+ for (const attestation of attestations) {
133
+ const slotNumber = attestation.payload.header.globalVariables.slotNumber.toString();
134
+ const proposalId = attestation.archive.toString();
135
+ const proposalMap = this.getProposalMap(slotNumber, proposalId);
136
+
137
+ if (proposalMap) {
138
+ const address = attestation.getSender().toString();
139
+ deletionPromises.push(proposalMap.delete(address));
140
+ this.log.debug(`Deleted attestation for slot ${slotNumber} from ${address}`);
141
+ }
142
+
143
+ if (proposalMap.size() === 0) {
144
+ deletionPromises.push(this.attestations.deleteValue(slotNumber, proposalId));
145
+ }
146
+ }
147
+
148
+ await Promise.all(deletionPromises);
149
+
150
+ this.metrics.recordRemovedObjects(attestations.length);
151
+ return Promise.resolve();
152
+ }
153
+ }
@@ -1,3 +1,5 @@
1
+ import { type P2PClientType } from '@aztec/circuit-types';
2
+
1
3
  import { type AttestationPool } from './attestation_pool/attestation_pool.js';
2
4
  import { type EpochProofQuotePool } from './epoch_proof_quote_pool/epoch_proof_quote_pool.js';
3
5
  import { type TxPool } from './tx_pool/tx_pool.js';
@@ -5,8 +7,8 @@ import { type TxPool } from './tx_pool/tx_pool.js';
5
7
  /**
6
8
  * A interface the combines all mempools
7
9
  */
8
- export interface MemPools {
10
+ export type MemPools<T extends P2PClientType = P2PClientType.Full> = {
9
11
  txPool: TxPool;
10
- attestationPool: AttestationPool;
12
+ attestationPool?: T extends P2PClientType.Full ? AttestationPool : undefined;
11
13
  epochProofQuotePool: EpochProofQuotePool;
12
- }
14
+ };
@@ -1,9 +1,11 @@
1
1
  import {
2
2
  type ClientProtocolCircuitVerifier,
3
3
  type L2BlockSource,
4
+ type P2PClientType,
4
5
  type Tx,
5
6
  type WorldStateSynchronizer,
6
7
  } from '@aztec/circuit-types';
8
+ import { type EpochCache } from '@aztec/epoch-cache';
7
9
  import { type DataStoreConfig } from '@aztec/kv-store/config';
8
10
  import { openTmpStore } from '@aztec/kv-store/lmdb';
9
11
  import { type TelemetryClient } from '@aztec/telemetry-client';
@@ -23,11 +25,11 @@ import { type Libp2p, type Libp2pOptions, createLibp2p } from 'libp2p';
23
25
  import { BootstrapNode } from '../bootstrap/bootstrap.js';
24
26
  import { type BootnodeConfig, type P2PConfig } from '../config.js';
25
27
  import { type MemPools } from '../mem_pools/interface.js';
26
- import { DiscV5Service } from '../service/discV5_service.js';
27
- import { LibP2PService } from '../service/libp2p_service.js';
28
- import { type PeerManager } from '../service/peer_manager.js';
29
- import { type P2PReqRespConfig } from '../service/reqresp/config.js';
30
- import { pingHandler, statusHandler } from '../service/reqresp/handlers.js';
28
+ import { DiscV5Service } from '../services/discv5/discV5_service.js';
29
+ import { LibP2PService } from '../services/libp2p/libp2p_service.js';
30
+ import { type PeerManager } from '../services/peer_manager.js';
31
+ import { type P2PReqRespConfig } from '../services/reqresp/config.js';
32
+ import { pingHandler, statusHandler } from '../services/reqresp/handlers.js';
31
33
  import {
32
34
  PING_PROTOCOL,
33
35
  type ReqRespSubProtocolHandlers,
@@ -35,8 +37,8 @@ import {
35
37
  STATUS_PROTOCOL,
36
38
  TX_REQ_PROTOCOL,
37
39
  noopValidator,
38
- } from '../service/reqresp/interface.js';
39
- import { ReqResp } from '../service/reqresp/reqresp.js';
40
+ } from '../services/reqresp/interface.js';
41
+ import { ReqResp } from '../services/reqresp/reqresp.js';
40
42
  import { type PubSubLibp2p } from '../util.js';
41
43
 
42
44
  /**
@@ -95,11 +97,13 @@ export async function createLibp2pNode(
95
97
  *
96
98
  *
97
99
  */
98
- export async function createTestLibP2PService(
100
+ export async function createTestLibP2PService<T extends P2PClientType>(
101
+ clientType: T,
99
102
  boostrapAddrs: string[] = [],
100
103
  l2BlockSource: L2BlockSource,
101
104
  worldStateSynchronizer: WorldStateSynchronizer,
102
- mempools: MemPools,
105
+ epochCache: EpochCache,
106
+ mempools: MemPools<T>,
103
107
  telemetry: TelemetryClient,
104
108
  port: number = 0,
105
109
  peerId?: PeerId,
@@ -123,12 +127,14 @@ export async function createTestLibP2PService(
123
127
  // No bootstrap nodes provided as the libp2p service will register them in the constructor
124
128
  const p2pNode = await createLibp2pNode([], peerId, port, /*enable gossip */ true, /**start */ false);
125
129
 
126
- return new LibP2PService(
130
+ return new LibP2PService<T>(
131
+ clientType,
127
132
  config,
128
133
  p2pNode as PubSubLibp2p,
129
134
  discoveryService,
130
135
  mempools,
131
136
  l2BlockSource,
137
+ epochCache,
132
138
  proofVerifier,
133
139
  worldStateSynchronizer,
134
140
  telemetry,
@@ -0,0 +1,26 @@
1
+ import { type BlockAttestation, type P2PValidator, PeerErrorSeverity } from '@aztec/circuit-types';
2
+ import { type EpochCache } from '@aztec/epoch-cache';
3
+
4
+ export class AttestationValidator implements P2PValidator<BlockAttestation> {
5
+ private epochCache: EpochCache;
6
+
7
+ constructor(epochCache: EpochCache) {
8
+ this.epochCache = epochCache;
9
+ }
10
+
11
+ async validate(message: BlockAttestation): Promise<PeerErrorSeverity | undefined> {
12
+ const { currentSlot, nextSlot } = await this.epochCache.getProposerInCurrentOrNextSlot();
13
+
14
+ const slotNumberBigInt = message.payload.header.globalVariables.slotNumber.toBigInt();
15
+ if (slotNumberBigInt !== currentSlot && slotNumberBigInt !== nextSlot) {
16
+ return PeerErrorSeverity.HighToleranceError;
17
+ }
18
+
19
+ const attester = message.getSender();
20
+ if (!(await this.epochCache.isInCommittee(attester))) {
21
+ return PeerErrorSeverity.HighToleranceError;
22
+ }
23
+
24
+ return undefined;
25
+ }
26
+ }
@@ -0,0 +1 @@
1
+ export * from './attestation_validator.js';
@@ -0,0 +1,29 @@
1
+ import { type BlockProposal, type P2PValidator, PeerErrorSeverity } from '@aztec/circuit-types';
2
+ import { type EpochCache } from '@aztec/epoch-cache';
3
+
4
+ export class BlockProposalValidator implements P2PValidator<BlockProposal> {
5
+ private epochCache: EpochCache;
6
+
7
+ constructor(epochCache: EpochCache) {
8
+ this.epochCache = epochCache;
9
+ }
10
+
11
+ async validate(block: BlockProposal): Promise<PeerErrorSeverity | undefined> {
12
+ const { currentProposer, nextProposer, currentSlot, nextSlot } =
13
+ await this.epochCache.getProposerInCurrentOrNextSlot();
14
+
15
+ // Check that the attestation is for the current or next slot
16
+ const slotNumberBigInt = block.payload.header.globalVariables.slotNumber.toBigInt();
17
+ if (slotNumberBigInt !== currentSlot && slotNumberBigInt !== nextSlot) {
18
+ return PeerErrorSeverity.HighToleranceError;
19
+ }
20
+
21
+ // Check that the block proposal is from the current or next proposer
22
+ const proposer = block.getSender();
23
+ if (!proposer.equals(currentProposer) && !proposer.equals(nextProposer)) {
24
+ return PeerErrorSeverity.HighToleranceError;
25
+ }
26
+
27
+ return undefined;
28
+ }
29
+ }
@@ -0,0 +1 @@
1
+ export * from './block_proposal_validator.js';
@@ -0,0 +1,22 @@
1
+ import { type EpochProofQuote, type P2PValidator, PeerErrorSeverity } from '@aztec/circuit-types';
2
+ import { type EpochCache } from '@aztec/epoch-cache';
3
+
4
+ export class EpochProofQuoteValidator implements P2PValidator<EpochProofQuote> {
5
+ private epochCache: EpochCache;
6
+
7
+ constructor(epochCache: EpochCache) {
8
+ this.epochCache = epochCache;
9
+ }
10
+
11
+ validate(message: EpochProofQuote): Promise<PeerErrorSeverity | undefined> {
12
+ const { epoch } = this.epochCache.getEpochAndSlotNow();
13
+
14
+ // Check that the epoch proof quote is for the current epoch
15
+ const epochToProve = message.payload.epochToProve;
16
+ if (epochToProve !== epoch && epochToProve !== epoch - 1n) {
17
+ return Promise.resolve(PeerErrorSeverity.HighToleranceError);
18
+ }
19
+
20
+ return Promise.resolve(undefined);
21
+ }
22
+ }
@@ -0,0 +1 @@
1
+ export { EpochProofQuoteValidator } from './epoch_proof_quote_validator.js';
@@ -0,0 +1,3 @@
1
+ export * from './tx_validator/index.js';
2
+ export * from './block_proposal_validator/index.js';
3
+ export * from './attestation_validator/index.js';
@@ -10,16 +10,18 @@ export class AggregateTxValidator<T extends Tx | ProcessedTx> implements TxValid
10
10
  this.#validators = validators;
11
11
  }
12
12
 
13
- async validateTxs(txs: T[]): Promise<[validTxs: T[], invalidTxs: T[]]> {
13
+ async validateTxs(txs: T[]): Promise<[validTxs: T[], invalidTxs: T[], skippedTxs: T[]]> {
14
14
  const invalidTxs: T[] = [];
15
+ const skippedTxs: T[] = [];
15
16
  let txPool = txs;
16
17
  for (const validator of this.#validators) {
17
- const [valid, invalid] = await validator.validateTxs(txPool);
18
+ const [valid, invalid, skipped] = await validator.validateTxs(txPool);
18
19
  invalidTxs.push(...invalid);
20
+ skippedTxs.push(...(skipped ?? []));
19
21
  txPool = valid;
20
22
  }
21
23
 
22
- return [txPool, invalidTxs];
24
+ return [txPool, invalidTxs, skippedTxs];
23
25
  }
24
26
 
25
27
  async validateTx(tx: T): Promise<boolean> {
@@ -1,9 +1,8 @@
1
1
  import { type AnyTx, Tx, type TxValidator } from '@aztec/circuit-types';
2
- import { Fr } from '@aztec/circuits.js';
3
2
  import { createLogger } from '@aztec/foundation/log';
4
3
 
5
4
  export interface NullifierSource {
6
- getNullifierIndex: (nullifier: Fr) => Promise<bigint | undefined>;
5
+ getNullifierIndices: (nullifiers: Buffer[]) => Promise<(bigint | undefined)[]>;
7
6
  }
8
7
 
9
8
  export class DoubleSpendTxValidator<T extends AnyTx> implements TxValidator<T> {
@@ -36,9 +35,7 @@ export class DoubleSpendTxValidator<T extends AnyTx> implements TxValidator<T> {
36
35
  }
37
36
 
38
37
  async #uniqueNullifiers(tx: AnyTx, thisBlockNullifiers: Set<bigint>): Promise<boolean> {
39
- const nullifiers = (tx instanceof Tx ? tx.data.getNonEmptyNullifiers() : tx.txEffect.nullifiers).map(x =>
40
- x.toBigInt(),
41
- );
38
+ const nullifiers = tx instanceof Tx ? tx.data.getNonEmptyNullifiers() : tx.txEffect.nullifiers;
42
39
 
43
40
  // Ditch this tx if it has repeated nullifiers
44
41
  const uniqueNullifiers = new Set(nullifiers);
@@ -49,16 +46,17 @@ export class DoubleSpendTxValidator<T extends AnyTx> implements TxValidator<T> {
49
46
 
50
47
  if (this.isValidatingBlock) {
51
48
  for (const nullifier of nullifiers) {
52
- if (thisBlockNullifiers.has(nullifier)) {
49
+ const nullifierBigInt = nullifier.toBigInt();
50
+ if (thisBlockNullifiers.has(nullifierBigInt)) {
53
51
  this.#log.warn(`Rejecting tx ${Tx.getHash(tx)} for repeating a nullifier in the same block`);
54
52
  return false;
55
53
  }
56
54
 
57
- thisBlockNullifiers.add(nullifier);
55
+ thisBlockNullifiers.add(nullifierBigInt);
58
56
  }
59
57
  }
60
58
 
61
- const nullifierIndexes = await Promise.all(nullifiers.map(n => this.#nullifierSource.getNullifierIndex(new Fr(n))));
59
+ const nullifierIndexes = await this.#nullifierSource.getNullifierIndices(nullifiers.map(n => n.toBuffer()));
62
60
 
63
61
  const hasDuplicates = nullifierIndexes.some(index => index !== undefined);
64
62
  if (hasDuplicates) {
@@ -8,29 +8,19 @@ import type { PeerId } from '@libp2p/interface';
8
8
  import { type Multiaddr, multiaddr } from '@multiformats/multiaddr';
9
9
  import EventEmitter from 'events';
10
10
 
11
- import type { P2PConfig } from '../config.js';
12
- import { convertToMultiaddr } from '../util.js';
13
- import { type PeerDiscoveryService, PeerDiscoveryState } from './service.js';
14
-
15
- export const AZTEC_ENR_KEY = 'aztec_network';
11
+ import type { P2PConfig } from '../../config.js';
12
+ import { convertToMultiaddr } from '../../util.js';
13
+ import { type PeerDiscoveryService, PeerDiscoveryState } from '../service.js';
14
+ import { AZTEC_ENR_KEY, AZTEC_NET, Discv5Event, PeerEvent } from '../types.js';
16
15
 
17
16
  const delayBeforeStart = 2000; // 2sec
18
17
 
19
- export enum AztecENR {
20
- devnet = 0x01,
21
- testnet = 0x02,
22
- mainnet = 0x03,
23
- }
24
-
25
- // TODO: Make this an env var
26
- export const AZTEC_NET = AztecENR.devnet;
27
-
28
18
  /**
29
19
  * Peer discovery service using Discv5.
30
20
  */
31
21
  export class DiscV5Service extends EventEmitter implements PeerDiscoveryService {
32
22
  /** The Discv5 instance */
33
- private discv5: Discv5;
23
+ private discv5: Discv5 & Discv5EventEmitter;
34
24
 
35
25
  /** This instance's ENR */
36
26
  private enr: SignableENR;
@@ -88,13 +78,8 @@ export class DiscV5Service extends EventEmitter implements PeerDiscoveryService
88
78
  metricsRegistry,
89
79
  });
90
80
 
91
- (this.discv5 as Discv5EventEmitter).on('discovered', (enr: ENR) => this.onDiscovered(enr));
92
- (this.discv5 as Discv5EventEmitter).on('enrAdded', async (enr: ENR) => {
93
- const multiAddrTcp = await enr.getFullMultiaddr('tcp');
94
- const multiAddrUdp = await enr.getFullMultiaddr('udp');
95
- this.logger.debug(`Added ENR ${enr.encodeTxt()}`, { multiAddrTcp, multiAddrUdp, nodeId: enr.nodeId });
96
- this.onDiscovered(enr);
97
- });
81
+ this.discv5.on(Discv5Event.DISCOVERED, this.onDiscovered.bind(this));
82
+ this.discv5.on(Discv5Event.ENR_ADDED, this.onEnrAdded.bind(this));
98
83
  }
99
84
 
100
85
  public async start(): Promise<void> {
@@ -168,10 +153,21 @@ export class DiscV5Service extends EventEmitter implements PeerDiscoveryService
168
153
  }
169
154
 
170
155
  public async stop(): Promise<void> {
156
+ await this.discv5.off(Discv5Event.DISCOVERED, this.onDiscovered);
157
+ await this.discv5.off(Discv5Event.ENR_ADDED, this.onEnrAdded);
158
+
171
159
  await this.discv5.stop();
160
+
172
161
  this.currentState = PeerDiscoveryState.STOPPED;
173
162
  }
174
163
 
164
+ private async onEnrAdded(enr: ENR) {
165
+ const multiAddrTcp = await enr.getFullMultiaddr('tcp');
166
+ const multiAddrUdp = await enr.getFullMultiaddr('udp');
167
+ this.logger.debug(`Added ENR ${enr.encodeTxt()}`, { multiAddrTcp, multiAddrUdp, nodeId: enr.nodeId });
168
+ this.onDiscovered(enr);
169
+ }
170
+
175
171
  private onDiscovered(enr: ENR) {
176
172
  // check the peer is an aztec peer
177
173
  const value = enr.kvs.get(AZTEC_ENR_KEY);
@@ -179,7 +175,7 @@ export class DiscV5Service extends EventEmitter implements PeerDiscoveryService
179
175
  const network = value[0];
180
176
  // check if the peer is on the same network
181
177
  if (network === AZTEC_NET) {
182
- this.emit('peer:discovered', enr);
178
+ this.emit(PeerEvent.DISCOVERED, enr);
183
179
  }
184
180
  }
185
181
  }
@@ -49,13 +49,31 @@ export function getMsgIdFn(message: Message) {
49
49
  return sha256(Buffer.concat(vec)).subarray(0, 20);
50
50
  }
51
51
 
52
+ /**
53
+ * Snappy transform for libp2p gossipsub
54
+ */
52
55
  export class SnappyTransform implements DataTransform {
56
+ // Topic string included to satisfy DataTransform interface
53
57
  inboundTransform(_topicStr: string, data: Uint8Array): Uint8Array {
54
- const uncompressed = Buffer.from(uncompressSync(Buffer.from(data), { asBuffer: true }));
55
- return new Uint8Array(uncompressed);
58
+ return this.inboundTransformNoTopic(Buffer.from(data));
59
+ }
60
+
61
+ public inboundTransformNoTopic(data: Buffer): Buffer {
62
+ if (data.length === 0) {
63
+ return data;
64
+ }
65
+ return Buffer.from(uncompressSync(data, { asBuffer: true }));
56
66
  }
57
67
 
68
+ // Topic string included to satisfy DataTransform interface
58
69
  outboundTransform(_topicStr: string, data: Uint8Array): Uint8Array {
59
- return new Uint8Array(compressSync(Buffer.from(data)));
70
+ return this.outboundTransformNoTopic(Buffer.from(data));
71
+ }
72
+
73
+ public outboundTransformNoTopic(data: Buffer): Buffer {
74
+ if (data.length === 0) {
75
+ return data;
76
+ }
77
+ return Buffer.from(compressSync(data));
60
78
  }
61
79
  }
@@ -0,0 +1,2 @@
1
+ export * from './service.js';
2
+ export * from './libp2p/libp2p_service.js';