@aztec/p2p 0.85.0 → 0.86.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dest/bootstrap/bootstrap.d.ts.map +1 -1
- package/dest/bootstrap/bootstrap.js +6 -3
- package/dest/client/p2p_client.d.ts +41 -3
- package/dest/client/p2p_client.d.ts.map +1 -1
- package/dest/client/p2p_client.js +58 -18
- package/dest/config.d.ts +13 -2
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +15 -3
- package/dest/enr/generate-enr.d.ts +1 -1
- package/dest/enr/generate-enr.d.ts.map +1 -1
- package/dest/enr/generate-enr.js +2 -2
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.js +11 -11
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.js +2 -2
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.js +4 -4
- package/dest/mem_pools/attestation_pool/mocks.d.ts +1 -1
- package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/mocks.js +2 -2
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts +3 -0
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.js +18 -0
- package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts +3 -0
- package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/memory_tx_pool.js +9 -0
- package/dest/mem_pools/tx_pool/tx_pool.d.ts +17 -0
- package/dest/mem_pools/tx_pool/tx_pool.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.js +57 -0
- package/dest/msg_validators/attestation_validator/attestation_validator.js +1 -1
- package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts +1 -0
- package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts.map +1 -1
- package/dest/msg_validators/block_proposal_validator/block_proposal_validator.js +6 -1
- package/dest/services/discv5/discV5_service.d.ts +2 -1
- package/dest/services/discv5/discV5_service.d.ts.map +1 -1
- package/dest/services/discv5/discV5_service.js +22 -7
- package/dest/services/dummy_service.d.ts +2 -2
- package/dest/services/dummy_service.d.ts.map +1 -1
- package/dest/services/dummy_service.js +2 -2
- package/dest/services/libp2p/libp2p_service.d.ts +3 -1
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
- package/dest/services/libp2p/libp2p_service.js +28 -12
- package/dest/services/peer-manager/peer_manager.d.ts +21 -2
- package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
- package/dest/services/peer-manager/peer_manager.js +63 -18
- package/dest/services/reqresp/connection-sampler/batch_connection_sampler.js +2 -2
- package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts +17 -1
- package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts.map +1 -1
- package/dest/services/reqresp/connection-sampler/connection_sampler.js +84 -36
- package/dest/services/reqresp/reqresp.d.ts +2 -2
- package/dest/services/reqresp/reqresp.d.ts.map +1 -1
- package/dest/services/reqresp/reqresp.js +7 -2
- package/dest/services/reqresp/status.d.ts +2 -1
- package/dest/services/reqresp/status.d.ts.map +1 -1
- package/dest/services/reqresp/status.js +3 -0
- package/dest/services/service.d.ts +4 -4
- package/dest/services/service.d.ts.map +1 -1
- package/dest/test-helpers/make-test-p2p-clients.d.ts +6 -1
- package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -1
- package/dest/test-helpers/make-test-p2p-clients.js +19 -2
- package/dest/testbench/p2p_client_testbench_worker.js +4 -1
- package/dest/util.d.ts.map +1 -1
- package/dest/util.js +5 -1
- package/package.json +12 -14
- package/src/bootstrap/bootstrap.ts +8 -4
- package/src/client/p2p_client.ts +212 -131
- package/src/config.ts +34 -4
- package/src/enr/generate-enr.ts +2 -2
- package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +11 -15
- package/src/mem_pools/attestation_pool/kv_attestation_pool.ts +2 -2
- package/src/mem_pools/attestation_pool/memory_attestation_pool.ts +4 -4
- package/src/mem_pools/attestation_pool/mocks.ts +3 -3
- package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +21 -0
- package/src/mem_pools/tx_pool/memory_tx_pool.ts +11 -0
- package/src/mem_pools/tx_pool/tx_pool.ts +20 -0
- package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +43 -0
- package/src/msg_validators/attestation_validator/attestation_validator.ts +1 -1
- package/src/msg_validators/block_proposal_validator/block_proposal_validator.ts +10 -1
- package/src/services/discv5/discV5_service.ts +32 -6
- package/src/services/dummy_service.ts +2 -2
- package/src/services/libp2p/libp2p_service.ts +37 -12
- package/src/services/peer-manager/peer_manager.ts +79 -22
- package/src/services/reqresp/connection-sampler/batch_connection_sampler.ts +2 -2
- package/src/services/reqresp/connection-sampler/connection_sampler.ts +82 -41
- package/src/services/reqresp/reqresp.ts +12 -6
- package/src/services/reqresp/status.ts +3 -0
- package/src/services/service.ts +4 -4
- package/src/test-helpers/make-test-p2p-clients.ts +20 -2
- package/src/testbench/p2p_client_testbench_worker.ts +3 -0
- package/src/util.ts +6 -1
package/src/config.ts
CHANGED
|
@@ -53,6 +53,11 @@ export interface P2PConfig extends P2PReqRespConfig, ChainConfig {
|
|
|
53
53
|
*/
|
|
54
54
|
p2pPort: number;
|
|
55
55
|
|
|
56
|
+
/**
|
|
57
|
+
* The port to broadcast the P2P service on (included in the node's ENR).
|
|
58
|
+
*/
|
|
59
|
+
p2pBroadcastPort?: number;
|
|
60
|
+
|
|
56
61
|
/**
|
|
57
62
|
* The IP address for the P2P service.
|
|
58
63
|
*/
|
|
@@ -175,6 +180,11 @@ export interface P2PConfig extends P2PReqRespConfig, ChainConfig {
|
|
|
175
180
|
*/
|
|
176
181
|
trustedPeers: string[];
|
|
177
182
|
|
|
183
|
+
/**
|
|
184
|
+
* A list of private peers.
|
|
185
|
+
*/
|
|
186
|
+
privatePeers: string[];
|
|
187
|
+
|
|
178
188
|
/**
|
|
179
189
|
* The maximum possible size of the P2P DB in KB. Overwrites the general dataStoreMapSizeKB.
|
|
180
190
|
*/
|
|
@@ -189,6 +199,8 @@ export interface P2PConfig extends P2PReqRespConfig, ChainConfig {
|
|
|
189
199
|
maxTxPoolSize: number;
|
|
190
200
|
}
|
|
191
201
|
|
|
202
|
+
export const DEFAULT_P2P_PORT = 40400;
|
|
203
|
+
|
|
192
204
|
export const p2pConfigMappings: ConfigMappingsType<P2PConfig> = {
|
|
193
205
|
p2pEnabled: {
|
|
194
206
|
env: 'P2P_ENABLED',
|
|
@@ -222,8 +234,12 @@ export const p2pConfigMappings: ConfigMappingsType<P2PConfig> = {
|
|
|
222
234
|
},
|
|
223
235
|
p2pPort: {
|
|
224
236
|
env: 'P2P_PORT',
|
|
225
|
-
description:
|
|
226
|
-
...numberConfigHelper(
|
|
237
|
+
description: `The port for the P2P service. Defaults to ${DEFAULT_P2P_PORT}`,
|
|
238
|
+
...numberConfigHelper(DEFAULT_P2P_PORT),
|
|
239
|
+
},
|
|
240
|
+
p2pBroadcastPort: {
|
|
241
|
+
env: 'P2P_BROADCAST_PORT',
|
|
242
|
+
description: `The port to broadcast the P2P service on (included in the node's ENR). Defaults to P2P_PORT.`,
|
|
227
243
|
},
|
|
228
244
|
p2pIp: {
|
|
229
245
|
env: 'P2P_IP',
|
|
@@ -357,7 +373,14 @@ export const p2pConfigMappings: ConfigMappingsType<P2PConfig> = {
|
|
|
357
373
|
trustedPeers: {
|
|
358
374
|
env: 'P2P_TRUSTED_PEERS',
|
|
359
375
|
parseEnv: (val: string) => val.split(','),
|
|
360
|
-
description: 'A list of trusted
|
|
376
|
+
description: 'A list of trusted peer ENRs that will always be persisted. Separated by commas.',
|
|
377
|
+
defaultValue: [],
|
|
378
|
+
},
|
|
379
|
+
privatePeers: {
|
|
380
|
+
env: 'P2P_PRIVATE_PEERS',
|
|
381
|
+
parseEnv: (val: string) => val.split(','),
|
|
382
|
+
description:
|
|
383
|
+
'A list of private peer ENRs that will always be persisted and not be used for discovery. Separated by commas.',
|
|
361
384
|
defaultValue: [],
|
|
362
385
|
},
|
|
363
386
|
p2pStoreMapSizeKb: {
|
|
@@ -398,7 +421,13 @@ export function getP2PDefaultConfig(): P2PConfig {
|
|
|
398
421
|
*/
|
|
399
422
|
export type BootnodeConfig = Pick<
|
|
400
423
|
P2PConfig,
|
|
401
|
-
|
|
424
|
+
| 'p2pIp'
|
|
425
|
+
| 'p2pPort'
|
|
426
|
+
| 'p2pBroadcastPort'
|
|
427
|
+
| 'peerIdPrivateKey'
|
|
428
|
+
| 'peerIdPrivateKeyPath'
|
|
429
|
+
| 'bootstrapNodes'
|
|
430
|
+
| 'listenAddress'
|
|
402
431
|
> &
|
|
403
432
|
Required<Pick<P2PConfig, 'p2pIp' | 'p2pPort'>> &
|
|
404
433
|
Pick<DataStoreConfig, 'dataDirectory' | 'dataStoreMapSizeKB'> &
|
|
@@ -407,6 +436,7 @@ export type BootnodeConfig = Pick<
|
|
|
407
436
|
const bootnodeConfigKeys: (keyof BootnodeConfig)[] = [
|
|
408
437
|
'p2pIp',
|
|
409
438
|
'p2pPort',
|
|
439
|
+
'p2pBroadcastPort',
|
|
410
440
|
'listenAddress',
|
|
411
441
|
'peerIdPrivateKey',
|
|
412
442
|
'peerIdPrivateKeyPath',
|
package/src/enr/generate-enr.ts
CHANGED
|
@@ -12,12 +12,12 @@ import { setAztecEnrKey } from '../versioning.js';
|
|
|
12
12
|
export async function createBootnodeENRandPeerId(
|
|
13
13
|
privateKey: string,
|
|
14
14
|
p2pIp: string,
|
|
15
|
-
|
|
15
|
+
p2pBroadcastPort: number,
|
|
16
16
|
l1ChainId: number,
|
|
17
17
|
): Promise<{ enr: SignableENR; peerId: PeerId }> {
|
|
18
18
|
const peerId = await createLibP2PPeerIdFromPrivateKey(privateKey);
|
|
19
19
|
const enr = SignableENR.createFromPeerId(peerId);
|
|
20
|
-
const publicAddr = multiaddr(convertToMultiaddr(p2pIp,
|
|
20
|
+
const publicAddr = multiaddr(convertToMultiaddr(p2pIp, p2pBroadcastPort, 'udp'));
|
|
21
21
|
enr.setLocationMultiaddr(publicAddr);
|
|
22
22
|
|
|
23
23
|
const config: ChainConfig = {
|
|
@@ -30,7 +30,7 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
|
|
|
30
30
|
|
|
31
31
|
const createAttestationsForSlot = (slotNumber: number) => {
|
|
32
32
|
const archive = Fr.random();
|
|
33
|
-
return
|
|
33
|
+
return signers.map(signer => mockAttestation(signer, slotNumber, archive));
|
|
34
34
|
};
|
|
35
35
|
|
|
36
36
|
// We compare buffers as the objects can have cached values attached to them which are not serialised
|
|
@@ -45,9 +45,7 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
|
|
|
45
45
|
it('should add attestations to pool', async () => {
|
|
46
46
|
const slotNumber = 420;
|
|
47
47
|
const archive = Fr.random();
|
|
48
|
-
const attestations =
|
|
49
|
-
signers.slice(0, -1).map(signer => mockAttestation(signer, slotNumber, archive)),
|
|
50
|
-
);
|
|
48
|
+
const attestations = signers.slice(0, -1).map(signer => mockAttestation(signer, slotNumber, archive));
|
|
51
49
|
|
|
52
50
|
await ap.addAttestations(attestations);
|
|
53
51
|
|
|
@@ -63,7 +61,7 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
|
|
|
63
61
|
compareAttestations(retrievedAttestationsForSlot, attestations);
|
|
64
62
|
|
|
65
63
|
// Add another one
|
|
66
|
-
const newAttestation =
|
|
64
|
+
const newAttestation = mockAttestation(signers[NUMBER_OF_SIGNERS_PER_TEST - 1], slotNumber, archive);
|
|
67
65
|
await ap.addAttestations([newAttestation]);
|
|
68
66
|
expect(metricsMock.recordAddedObjects).toHaveBeenCalledWith(1);
|
|
69
67
|
const retrievedAttestationsAfterAdd = await ap.getAttestationsForSlotAndProposal(
|
|
@@ -96,7 +94,7 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
|
|
|
96
94
|
const attestations: BlockAttestation[] = [];
|
|
97
95
|
const signer = signers[0];
|
|
98
96
|
for (let i = 0; i < NUMBER_OF_SIGNERS_PER_TEST; i++) {
|
|
99
|
-
attestations.push(
|
|
97
|
+
attestations.push(mockAttestation(signer, slotNumber, archive, txs));
|
|
100
98
|
}
|
|
101
99
|
|
|
102
100
|
// Add them to store and check we end up with only one
|
|
@@ -106,7 +104,7 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
|
|
|
106
104
|
expect(retreivedAttestations.length).toBe(1);
|
|
107
105
|
expect(retreivedAttestations[0].toBuffer()).toEqual(attestations[0].toBuffer());
|
|
108
106
|
expect(retreivedAttestations[0].payload.txHashes).toEqual(txs);
|
|
109
|
-
expect(
|
|
107
|
+
expect(retreivedAttestations[0].getSender().toString()).toEqual(signer.address.toString());
|
|
110
108
|
|
|
111
109
|
// Try adding them on another operation and check they are still not duplicated
|
|
112
110
|
await ap.addAttestations([attestations[0]]);
|
|
@@ -115,7 +113,7 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
|
|
|
115
113
|
|
|
116
114
|
it('should store attestations by differing slot', async () => {
|
|
117
115
|
const slotNumbers = [1, 2, 3, 4];
|
|
118
|
-
const attestations =
|
|
116
|
+
const attestations = signers.map((signer, i) => mockAttestation(signer, slotNumbers[i]));
|
|
119
117
|
|
|
120
118
|
await ap.addAttestations(attestations);
|
|
121
119
|
|
|
@@ -133,9 +131,7 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
|
|
|
133
131
|
it('should store attestations by differing slot and archive', async () => {
|
|
134
132
|
const slotNumbers = [1, 1, 2, 3];
|
|
135
133
|
const archives = [Fr.random(), Fr.random(), Fr.random(), Fr.random()];
|
|
136
|
-
const attestations =
|
|
137
|
-
signers.map((signer, i) => mockAttestation(signer, slotNumbers[i], archives[i])),
|
|
138
|
-
);
|
|
134
|
+
const attestations = signers.map((signer, i) => mockAttestation(signer, slotNumbers[i], archives[i]));
|
|
139
135
|
|
|
140
136
|
await ap.addAttestations(attestations);
|
|
141
137
|
|
|
@@ -153,7 +149,7 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
|
|
|
153
149
|
it('should delete attestations', async () => {
|
|
154
150
|
const slotNumber = 420;
|
|
155
151
|
const archive = Fr.random();
|
|
156
|
-
const attestations =
|
|
152
|
+
const attestations = signers.map(signer => mockAttestation(signer, slotNumber, archive));
|
|
157
153
|
const proposalId = attestations[0].archive.toString();
|
|
158
154
|
|
|
159
155
|
await ap.addAttestations(attestations);
|
|
@@ -175,7 +171,7 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
|
|
|
175
171
|
it('should blanket delete attestations per slot', async () => {
|
|
176
172
|
const slotNumber = 420;
|
|
177
173
|
const archive = Fr.random();
|
|
178
|
-
const attestations =
|
|
174
|
+
const attestations = signers.map(signer => mockAttestation(signer, slotNumber, archive));
|
|
179
175
|
const proposalId = attestations[0].archive.toString();
|
|
180
176
|
|
|
181
177
|
await ap.addAttestations(attestations);
|
|
@@ -193,12 +189,12 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
|
|
|
193
189
|
it('should blanket delete attestations per slot and proposal', async () => {
|
|
194
190
|
const slotNumber = 420;
|
|
195
191
|
const archive = Fr.random();
|
|
196
|
-
const attestations =
|
|
192
|
+
const attestations = signers.map(signer => mockAttestation(signer, slotNumber, archive));
|
|
197
193
|
const proposalId = attestations[0].archive.toString();
|
|
198
194
|
|
|
199
195
|
// Add another set of attestations with a different proposalId, yet the same slot
|
|
200
196
|
const archive2 = Fr.random();
|
|
201
|
-
const attestations2 =
|
|
197
|
+
const attestations2 = signers.map(signer => mockAttestation(signer, slotNumber, archive2));
|
|
202
198
|
const proposalId2 = attestations2[0].archive.toString();
|
|
203
199
|
|
|
204
200
|
await ap.addAttestations(attestations);
|
|
@@ -48,7 +48,7 @@ export class KvAttestationPool implements AttestationPool {
|
|
|
48
48
|
for (const attestation of attestations) {
|
|
49
49
|
const slotNumber = attestation.payload.header.globalVariables.slotNumber;
|
|
50
50
|
const proposalId = attestation.archive;
|
|
51
|
-
const address =
|
|
51
|
+
const address = attestation.getSender().toString();
|
|
52
52
|
|
|
53
53
|
await this.attestations.set(this.getAttestationKey(slotNumber, proposalId, address), attestation.toBuffer());
|
|
54
54
|
|
|
@@ -160,7 +160,7 @@ export class KvAttestationPool implements AttestationPool {
|
|
|
160
160
|
for (const attestation of attestations) {
|
|
161
161
|
const slotNumber = attestation.payload.header.globalVariables.slotNumber;
|
|
162
162
|
const proposalId = attestation.archive;
|
|
163
|
-
const address =
|
|
163
|
+
const address = attestation.getSender().toString();
|
|
164
164
|
|
|
165
165
|
await this.attestations.delete(this.getAttestationKey(slotNumber, proposalId, address));
|
|
166
166
|
await this.attestationsForProposal.deleteValue(
|
|
@@ -34,13 +34,13 @@ export class InMemoryAttestationPool implements AttestationPool {
|
|
|
34
34
|
return Promise.resolve([]);
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
public
|
|
37
|
+
public addAttestations(attestations: BlockAttestation[]): Promise<void> {
|
|
38
38
|
for (const attestation of attestations) {
|
|
39
39
|
// Perf: order and group by slot before insertion
|
|
40
40
|
const slotNumber = attestation.payload.header.globalVariables.slotNumber;
|
|
41
41
|
|
|
42
42
|
const proposalId = attestation.archive.toString();
|
|
43
|
-
const address =
|
|
43
|
+
const address = attestation.getSender();
|
|
44
44
|
|
|
45
45
|
const slotAttestationMap = getSlotOrDefault(this.attestations, slotNumber.toBigInt());
|
|
46
46
|
const proposalAttestationMap = getProposalOrDefault(slotAttestationMap, proposalId);
|
|
@@ -118,7 +118,7 @@ export class InMemoryAttestationPool implements AttestationPool {
|
|
|
118
118
|
return Promise.resolve();
|
|
119
119
|
}
|
|
120
120
|
|
|
121
|
-
public
|
|
121
|
+
public deleteAttestations(attestations: BlockAttestation[]): Promise<void> {
|
|
122
122
|
for (const attestation of attestations) {
|
|
123
123
|
const slotNumber = attestation.payload.header.globalVariables.slotNumber;
|
|
124
124
|
const slotAttestationMap = this.attestations.get(slotNumber.toBigInt());
|
|
@@ -126,7 +126,7 @@ export class InMemoryAttestationPool implements AttestationPool {
|
|
|
126
126
|
const proposalId = attestation.archive.toString();
|
|
127
127
|
const proposalAttestationMap = getProposalOrDefault(slotAttestationMap, proposalId);
|
|
128
128
|
if (proposalAttestationMap) {
|
|
129
|
-
const address =
|
|
129
|
+
const address = attestation.getSender();
|
|
130
130
|
proposalAttestationMap.delete(address.toString());
|
|
131
131
|
this.log.debug(`Deleted attestation for slot ${slotNumber} from ${address}`);
|
|
132
132
|
}
|
|
@@ -27,17 +27,17 @@ export const generateAccount = (): LocalAccount => {
|
|
|
27
27
|
* @param slot The slot number the attestation is for
|
|
28
28
|
* @returns A Block Attestation
|
|
29
29
|
*/
|
|
30
|
-
export const mockAttestation =
|
|
30
|
+
export const mockAttestation = (
|
|
31
31
|
signer: Secp256k1Signer,
|
|
32
32
|
slot: number = 0,
|
|
33
33
|
archive: Fr = Fr.random(),
|
|
34
34
|
txs: TxHash[] = [0, 1, 2, 3, 4, 5].map(() => TxHash.random()),
|
|
35
|
-
):
|
|
35
|
+
): BlockAttestation => {
|
|
36
36
|
// Use arbitrary numbers for all other than slot
|
|
37
37
|
const header = makeHeader(1, 2, slot);
|
|
38
38
|
const payload = new ConsensusPayload(header, archive, txs);
|
|
39
39
|
|
|
40
|
-
const hash =
|
|
40
|
+
const hash = getHashedSignaturePayloadEthSignedMessage(payload, SignatureDomainSeparator.blockAttestation);
|
|
41
41
|
const signature = signer.sign(hash);
|
|
42
42
|
|
|
43
43
|
return new BlockAttestation(payload, signature);
|
|
@@ -218,6 +218,22 @@ export class AztecKVTxPool implements TxPool {
|
|
|
218
218
|
return undefined;
|
|
219
219
|
}
|
|
220
220
|
|
|
221
|
+
async getTxsByHash(txHashes: TxHash[]): Promise<(Tx | undefined)[]> {
|
|
222
|
+
const txs = await Promise.all(txHashes.map(txHash => this.#txs.getAsync(txHash.toString())));
|
|
223
|
+
return txs.map((buffer, index) => {
|
|
224
|
+
if (buffer) {
|
|
225
|
+
const tx = Tx.fromBuffer(buffer);
|
|
226
|
+
tx.setTxHash(txHashes[index]);
|
|
227
|
+
return tx;
|
|
228
|
+
}
|
|
229
|
+
return undefined;
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
async hasTxs(txHashes: TxHash[]): Promise<boolean[]> {
|
|
234
|
+
return await Promise.all(txHashes.map(txHash => this.#txs.hasAsync(txHash.toString())));
|
|
235
|
+
}
|
|
236
|
+
|
|
221
237
|
/**
|
|
222
238
|
* Checks if an archived tx exists and returns it.
|
|
223
239
|
* @param txHash - The tx hash.
|
|
@@ -341,6 +357,11 @@ export class AztecKVTxPool implements TxPool {
|
|
|
341
357
|
return vals.map(x => TxHash.fromString(x));
|
|
342
358
|
}
|
|
343
359
|
|
|
360
|
+
public setMaxTxPoolSize(maxSizeBytes: number | undefined): Promise<void> {
|
|
361
|
+
this.#maxTxPoolSize = maxSizeBytes;
|
|
362
|
+
return Promise.resolve();
|
|
363
|
+
}
|
|
364
|
+
|
|
344
365
|
/**
|
|
345
366
|
* Creates a GasTxValidator instance.
|
|
346
367
|
* @param db - DB for the validator to use
|
|
@@ -103,6 +103,13 @@ export class InMemoryTxPool implements TxPool {
|
|
|
103
103
|
return Promise.resolve(result === undefined ? undefined : Tx.clone(result));
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
+
getTxsByHash(txHashes: TxHash[]): Promise<(Tx | undefined)[]> {
|
|
107
|
+
return Promise.all(txHashes.map(txHash => this.getTxByHash(txHash)));
|
|
108
|
+
}
|
|
109
|
+
hasTxs(txHashes: TxHash[]): Promise<boolean[]> {
|
|
110
|
+
return Promise.resolve(txHashes.map(txHash => this.txs.has(txHash.toBigInt())));
|
|
111
|
+
}
|
|
112
|
+
|
|
106
113
|
public getArchivedTxByHash(): Promise<Tx | undefined> {
|
|
107
114
|
return Promise.resolve(undefined);
|
|
108
115
|
}
|
|
@@ -171,4 +178,8 @@ export class InMemoryTxPool implements TxPool {
|
|
|
171
178
|
public getAllTxHashes(): Promise<TxHash[]> {
|
|
172
179
|
return Promise.resolve(Array.from(this.txs.keys()).map(x => TxHash.fromBigInt(x)));
|
|
173
180
|
}
|
|
181
|
+
|
|
182
|
+
setMaxTxPoolSize(_maxSizeBytes: number | undefined): Promise<void> {
|
|
183
|
+
return Promise.resolve();
|
|
184
|
+
}
|
|
174
185
|
}
|
|
@@ -17,6 +17,20 @@ export interface TxPool {
|
|
|
17
17
|
*/
|
|
18
18
|
getTxByHash(txHash: TxHash): Promise<Tx | undefined>;
|
|
19
19
|
|
|
20
|
+
/**
|
|
21
|
+
* Checks if transactions exist in the pool and returns them.
|
|
22
|
+
* @param txHashes - The hashes of the transactions
|
|
23
|
+
* @returns The transactions, if found, 'undefined' otherwise.
|
|
24
|
+
*/
|
|
25
|
+
getTxsByHash(txHashes: TxHash[]): Promise<(Tx | undefined)[]>;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Checks if transactions exist in the pool
|
|
29
|
+
* @param txHashes - The hashes of the transactions to check for
|
|
30
|
+
* @returns True or False for each tx hash
|
|
31
|
+
*/
|
|
32
|
+
hasTxs(txHashes: TxHash[]): Promise<boolean[]>;
|
|
33
|
+
|
|
20
34
|
/**
|
|
21
35
|
* Checks if an archived transaction exists in the pool and returns it.
|
|
22
36
|
* @param txHash - The hash of the transaction, used as an ID.
|
|
@@ -73,4 +87,10 @@ export interface TxPool {
|
|
|
73
87
|
* @returns Pending or mined depending on its status, or undefined if not found.
|
|
74
88
|
*/
|
|
75
89
|
getTxStatus(txHash: TxHash): Promise<'pending' | 'mined' | undefined>;
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Configure the maximum size of the tx pool
|
|
93
|
+
* @param maxSizeBytes - The maximum size in bytes of the mempool. Set to undefined to disable it
|
|
94
|
+
*/
|
|
95
|
+
setMaxTxPoolSize(maxSizeBytes: number | undefined): Promise<void>;
|
|
76
96
|
}
|
|
@@ -110,6 +110,49 @@ export function describeTxPool(getTxPool: () => TxPool) {
|
|
|
110
110
|
);
|
|
111
111
|
});
|
|
112
112
|
|
|
113
|
+
it('Returns txs by their hash', async () => {
|
|
114
|
+
const tx1 = await mockTx(1);
|
|
115
|
+
const tx2 = await mockTx(2);
|
|
116
|
+
const tx3 = await mockTx(3);
|
|
117
|
+
|
|
118
|
+
await pool.addTxs([tx1, tx2, tx3]);
|
|
119
|
+
|
|
120
|
+
const requestedTxs = await pool.getTxsByHash([await tx1.getTxHash(), await tx3.getTxHash()]);
|
|
121
|
+
expect(requestedTxs).toHaveLength(2);
|
|
122
|
+
expect(requestedTxs).toEqual(expect.arrayContaining([tx1, tx3]));
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it('Returns a large number of transactions by their hash', async () => {
|
|
126
|
+
const numTxs = 1000;
|
|
127
|
+
const txs = await Promise.all(Array.from({ length: numTxs }, (_, i) => mockTx(i)));
|
|
128
|
+
const hashes = await Promise.all(txs.map(tx => tx.getTxHash()));
|
|
129
|
+
await pool.addTxs(txs);
|
|
130
|
+
const requestedTxs = await pool.getTxsByHash(hashes);
|
|
131
|
+
expect(requestedTxs).toHaveLength(numTxs);
|
|
132
|
+
expect(requestedTxs).toEqual(expect.arrayContaining(txs));
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it('Returns whether or not txs exist', async () => {
|
|
136
|
+
const tx1 = await mockTx(1);
|
|
137
|
+
const tx2 = await mockTx(2);
|
|
138
|
+
const tx3 = await mockTx(3);
|
|
139
|
+
|
|
140
|
+
await pool.addTxs([tx1, tx2, tx3]);
|
|
141
|
+
|
|
142
|
+
const tx4 = await mockTx(4);
|
|
143
|
+
const tx5 = await mockTx(5);
|
|
144
|
+
|
|
145
|
+
const availability = await pool.hasTxs([
|
|
146
|
+
await tx1.getTxHash(),
|
|
147
|
+
await tx2.getTxHash(),
|
|
148
|
+
await tx3.getTxHash(),
|
|
149
|
+
await tx4.getTxHash(),
|
|
150
|
+
await tx5.getTxHash(),
|
|
151
|
+
]);
|
|
152
|
+
expect(availability).toHaveLength(5);
|
|
153
|
+
expect(availability).toEqual(expect.arrayContaining([true, true, true, false, false]));
|
|
154
|
+
});
|
|
155
|
+
|
|
113
156
|
it('Returns pending tx hashes sorted by priority', async () => {
|
|
114
157
|
const withPriorityFee = (tx: Tx, fee: number) => {
|
|
115
158
|
unfreeze(tx.data.constants.txContext.gasSettings).maxPriorityFeesPerGas = new GasFees(fee, fee);
|
|
@@ -16,7 +16,7 @@ export class AttestationValidator implements P2PValidator<BlockAttestation> {
|
|
|
16
16
|
return PeerErrorSeverity.HighToleranceError;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
const attester =
|
|
19
|
+
const attester = message.getSender();
|
|
20
20
|
if (!(await this.epochCache.isInCommittee(attester))) {
|
|
21
21
|
return PeerErrorSeverity.HighToleranceError;
|
|
22
22
|
}
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import type { EpochCacheInterface } from '@aztec/epoch-cache';
|
|
2
|
+
import { type Logger, createLogger } from '@aztec/foundation/log';
|
|
2
3
|
import { type BlockProposal, type P2PValidator, PeerErrorSeverity } from '@aztec/stdlib/p2p';
|
|
3
4
|
|
|
4
5
|
export class BlockProposalValidator implements P2PValidator<BlockProposal> {
|
|
5
6
|
private epochCache: EpochCacheInterface;
|
|
7
|
+
private logger: Logger;
|
|
6
8
|
|
|
7
9
|
constructor(epochCache: EpochCacheInterface) {
|
|
8
10
|
this.epochCache = epochCache;
|
|
11
|
+
this.logger = createLogger('p2p:block_proposal_validator');
|
|
9
12
|
}
|
|
10
13
|
|
|
11
14
|
async validate(block: BlockProposal): Promise<PeerErrorSeverity | undefined> {
|
|
@@ -15,12 +18,18 @@ export class BlockProposalValidator implements P2PValidator<BlockProposal> {
|
|
|
15
18
|
// Check that the attestation is for the current or next slot
|
|
16
19
|
const slotNumberBigInt = block.payload.header.globalVariables.slotNumber.toBigInt();
|
|
17
20
|
if (slotNumberBigInt !== currentSlot && slotNumberBigInt !== nextSlot) {
|
|
21
|
+
this.logger.debug(
|
|
22
|
+
`Penalizing peer for invalid slot number ${slotNumberBigInt}, current slot: ${currentSlot}, next slot: ${nextSlot}`,
|
|
23
|
+
);
|
|
18
24
|
return PeerErrorSeverity.HighToleranceError;
|
|
19
25
|
}
|
|
20
26
|
|
|
21
27
|
// Check that the block proposal is from the current or next proposer
|
|
22
|
-
const proposer =
|
|
28
|
+
const proposer = block.getSender();
|
|
23
29
|
if (!proposer.equals(currentProposer) && !proposer.equals(nextProposer)) {
|
|
30
|
+
this.logger.debug(
|
|
31
|
+
`Penalizing peer for invalid proposer ${proposer.toString()}, current proposer: ${currentProposer.toString()}, next proposer: ${nextProposer.toString()}`,
|
|
32
|
+
);
|
|
24
33
|
return PeerErrorSeverity.HighToleranceError;
|
|
25
34
|
}
|
|
26
35
|
|
|
@@ -34,6 +34,7 @@ export class DiscV5Service extends EventEmitter implements PeerDiscoveryService
|
|
|
34
34
|
|
|
35
35
|
private bootstrapNodePeerIds: PeerId[] = [];
|
|
36
36
|
public bootstrapNodeEnrs: ENR[] = [];
|
|
37
|
+
private trustedPeerEnrs: ENR[] = [];
|
|
37
38
|
|
|
38
39
|
private startTime = 0;
|
|
39
40
|
|
|
@@ -51,21 +52,33 @@ export class DiscV5Service extends EventEmitter implements PeerDiscoveryService
|
|
|
51
52
|
configOverrides: Partial<IDiscv5CreateOptions> = {},
|
|
52
53
|
) {
|
|
53
54
|
super();
|
|
54
|
-
const { p2pIp, p2pPort, bootstrapNodes } = config;
|
|
55
|
+
const { p2pIp, p2pPort, p2pBroadcastPort, bootstrapNodes, trustedPeers, privatePeers } = config;
|
|
56
|
+
|
|
55
57
|
this.bootstrapNodeEnrs = bootstrapNodes.map(x => ENR.decodeTxt(x));
|
|
58
|
+
const privatePeerEnrs = new Set(privatePeers);
|
|
59
|
+
this.trustedPeerEnrs = trustedPeers.filter(x => !privatePeerEnrs.has(x)).map(x => ENR.decodeTxt(x));
|
|
56
60
|
// create ENR from PeerId
|
|
57
61
|
this.enr = SignableENR.createFromPeerId(peerId);
|
|
58
62
|
// Add aztec identification to ENR
|
|
59
63
|
this.versions = setAztecEnrKey(this.enr, config);
|
|
60
64
|
|
|
65
|
+
// If no overridden broadcast port is provided, use the p2p port as the broadcast port
|
|
66
|
+
if (!p2pBroadcastPort) {
|
|
67
|
+
this.logger.warn('No p2pBroadcastPort provided, using p2pPort as broadcast port');
|
|
68
|
+
config.p2pBroadcastPort = p2pPort;
|
|
69
|
+
}
|
|
70
|
+
|
|
61
71
|
const bindAddrs: any = {
|
|
62
72
|
ip4: multiaddr(convertToMultiaddr(config.listenAddress, p2pPort, 'udp')),
|
|
63
73
|
};
|
|
64
74
|
|
|
65
75
|
if (p2pIp) {
|
|
66
|
-
const multiAddrTcp = multiaddr(
|
|
67
|
-
|
|
68
|
-
|
|
76
|
+
const multiAddrTcp = multiaddr(
|
|
77
|
+
`${convertToMultiaddr(p2pIp!, config.p2pBroadcastPort!, 'tcp')}/p2p/${peerId.toString()}`,
|
|
78
|
+
);
|
|
79
|
+
const multiAddrUdp = multiaddr(
|
|
80
|
+
`${convertToMultiaddr(p2pIp!, config.p2pBroadcastPort!, 'udp')}/p2p/${peerId.toString()}`,
|
|
81
|
+
);
|
|
69
82
|
|
|
70
83
|
// set location multiaddr in ENR record
|
|
71
84
|
this.enr.setLocationMultiaddr(multiAddrUdp);
|
|
@@ -113,7 +126,8 @@ export class DiscV5Service extends EventEmitter implements PeerDiscoveryService
|
|
|
113
126
|
|
|
114
127
|
private onMultiaddrUpdated(m: Multiaddr) {
|
|
115
128
|
// We want to update our tcp port to match the udp port
|
|
116
|
-
|
|
129
|
+
// p2pBroadcastPort is optional on config, however it is set to default within the p2p client factory
|
|
130
|
+
const multiAddrTcp = multiaddr(convertToMultiaddr(m.nodeAddress().address, this.config.p2pBroadcastPort!, 'tcp'));
|
|
117
131
|
this.enr.setLocationMultiaddr(multiAddrTcp);
|
|
118
132
|
this.logger.info('Multiaddr updated', { multiaddr: multiAddrTcp.toString() });
|
|
119
133
|
}
|
|
@@ -159,6 +173,18 @@ export class DiscV5Service extends EventEmitter implements PeerDiscoveryService
|
|
|
159
173
|
}
|
|
160
174
|
}
|
|
161
175
|
}
|
|
176
|
+
|
|
177
|
+
// Add trusted peer ENRs if provided
|
|
178
|
+
if (this.trustedPeerEnrs?.length) {
|
|
179
|
+
this.logger.info(
|
|
180
|
+
`Adding ${this.trustedPeerEnrs.length} trusted peer ENRs: ${this.trustedPeerEnrs
|
|
181
|
+
.map(enr => enr.encodeTxt())
|
|
182
|
+
.join(', ')}`,
|
|
183
|
+
);
|
|
184
|
+
for (const enr of this.trustedPeerEnrs) {
|
|
185
|
+
this.discv5.addEnr(enr);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
162
188
|
}
|
|
163
189
|
|
|
164
190
|
public async runRandomNodesQuery(): Promise<void> {
|
|
@@ -180,7 +206,7 @@ export class DiscV5Service extends EventEmitter implements PeerDiscoveryService
|
|
|
180
206
|
}
|
|
181
207
|
}
|
|
182
208
|
|
|
183
|
-
public
|
|
209
|
+
public getKadValues(): ENR[] {
|
|
184
210
|
return this.discv5.kadValues();
|
|
185
211
|
}
|
|
186
212
|
|
|
@@ -111,9 +111,9 @@ export class DummyPeerDiscoveryService extends EventEmitter implements PeerDisco
|
|
|
111
111
|
}
|
|
112
112
|
/**
|
|
113
113
|
* Called to discover peers in the network.
|
|
114
|
-
* @returns An array of
|
|
114
|
+
* @returns An array of Enrs.
|
|
115
115
|
*/
|
|
116
|
-
public
|
|
116
|
+
public getKadValues() {
|
|
117
117
|
return [];
|
|
118
118
|
}
|
|
119
119
|
|