@aztec/p2p 0.47.1 → 0.49.2
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 +2 -6
- package/dest/bootstrap/bootstrap.d.ts.map +1 -1
- package/dest/bootstrap/bootstrap.js +1 -1
- package/dest/client/mocks.js +2 -2
- package/dest/client/p2p_client.js +2 -2
- package/dest/config.d.ts +10 -12
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +89 -26
- package/dest/service/libp2p_service.d.ts +1 -2
- package/dest/service/libp2p_service.d.ts.map +1 -1
- package/dest/service/libp2p_service.js +20 -33
- package/dest/tx_pool/aztec_kv_tx_pool.d.ts.map +1 -1
- package/dest/tx_pool/aztec_kv_tx_pool.js +24 -6
- package/dest/tx_pool/instrumentation.d.ts +4 -2
- package/dest/tx_pool/instrumentation.d.ts.map +1 -1
- package/dest/tx_pool/instrumentation.js +21 -8
- package/dest/tx_pool/memory_tx_pool.d.ts.map +1 -1
- package/dest/tx_pool/memory_tx_pool.js +13 -5
- package/package.json +6 -6
- package/src/bootstrap/bootstrap.ts +2 -9
- package/src/client/mocks.ts +1 -1
- package/src/client/p2p_client.ts +1 -1
- package/src/config.ts +113 -57
- package/src/service/libp2p_service.ts +21 -34
- package/src/tx_pool/aztec_kv_tx_pool.ts +24 -5
- package/src/tx_pool/instrumentation.ts +23 -8
- package/src/tx_pool/memory_tx_pool.ts +16 -4
- package/dest/service/tx_messages.d.ts +0 -14
- package/dest/service/tx_messages.d.ts.map +0 -1
- package/dest/service/tx_messages.js +0 -14
- package/src/service/tx_messages.ts +0 -22
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { Tx } from '@aztec/circuit-types';
|
|
2
|
-
import { SerialQueue } from '@aztec/foundation/fifo';
|
|
1
|
+
import { type Gossipable, type RawGossipMessage, TopicType, TopicTypeMap, Tx } from '@aztec/circuit-types';
|
|
3
2
|
import { createDebugLogger } from '@aztec/foundation/log';
|
|
3
|
+
import { SerialQueue } from '@aztec/foundation/queue';
|
|
4
4
|
import { RunningPromise } from '@aztec/foundation/running-promise';
|
|
5
5
|
import type { AztecKVStore } from '@aztec/kv-store';
|
|
6
6
|
|
|
@@ -21,7 +21,6 @@ import { convertToMultiaddr } from '../util.js';
|
|
|
21
21
|
import { AztecDatastore } from './data_store.js';
|
|
22
22
|
import { PeerManager } from './peer_manager.js';
|
|
23
23
|
import type { P2PService, PeerDiscoveryService } from './service.js';
|
|
24
|
-
import { AztecTxMessageCreator } from './tx_messages.js';
|
|
25
24
|
|
|
26
25
|
export interface PubSubLibp2p extends Libp2p {
|
|
27
26
|
services: {
|
|
@@ -49,7 +48,6 @@ export async function createLibP2PPeerId(privateKey?: string): Promise<PeerId> {
|
|
|
49
48
|
*/
|
|
50
49
|
export class LibP2PService implements P2PService {
|
|
51
50
|
private jobQueue: SerialQueue = new SerialQueue();
|
|
52
|
-
private messageCreator: AztecTxMessageCreator;
|
|
53
51
|
private peerManager: PeerManager;
|
|
54
52
|
private discoveryRunningPromise?: RunningPromise;
|
|
55
53
|
constructor(
|
|
@@ -59,7 +57,6 @@ export class LibP2PService implements P2PService {
|
|
|
59
57
|
private txPool: TxPool,
|
|
60
58
|
private logger = createDebugLogger('aztec:libp2p_service'),
|
|
61
59
|
) {
|
|
62
|
-
this.messageCreator = new AztecTxMessageCreator(config.txGossipVersion);
|
|
63
60
|
this.peerManager = new PeerManager(node, peerDiscoveryService, config, logger);
|
|
64
61
|
}
|
|
65
62
|
|
|
@@ -89,20 +86,22 @@ export class LibP2PService implements P2PService {
|
|
|
89
86
|
this.logger.info(`Started P2P client with Peer ID ${this.node.peerId.toString()}`);
|
|
90
87
|
|
|
91
88
|
// Subscribe to standard GossipSub topics by default
|
|
92
|
-
|
|
89
|
+
for (const topic in TopicType) {
|
|
90
|
+
this.subscribeToTopic(TopicTypeMap[topic].p2pTopic);
|
|
91
|
+
}
|
|
93
92
|
|
|
94
93
|
// add GossipSub listener
|
|
95
94
|
this.node.services.pubsub.addEventListener('gossipsub:message', async e => {
|
|
96
95
|
const { msg } = e.detail;
|
|
97
96
|
this.logger.debug(`Received PUBSUB message.`);
|
|
98
97
|
|
|
99
|
-
await this.jobQueue.put(() => this.handleNewGossipMessage(msg
|
|
98
|
+
await this.jobQueue.put(() => this.handleNewGossipMessage(msg));
|
|
100
99
|
});
|
|
101
100
|
|
|
102
101
|
// Start running promise for peer discovery
|
|
103
102
|
this.discoveryRunningPromise = new RunningPromise(() => {
|
|
104
103
|
this.peerManager.discover();
|
|
105
|
-
}, this.config.
|
|
104
|
+
}, this.config.peerCheckIntervalMS);
|
|
106
105
|
this.discoveryRunningPromise.start();
|
|
107
106
|
}
|
|
108
107
|
|
|
@@ -142,20 +141,6 @@ export class LibP2PService implements P2PService {
|
|
|
142
141
|
|
|
143
142
|
const datastore = new AztecDatastore(store);
|
|
144
143
|
|
|
145
|
-
// The autonat service seems quite problematic in that using it seems to cause a lot of attempts
|
|
146
|
-
// to dial ephemeral ports. I suspect that it works better if you can get the uPNPnat service to
|
|
147
|
-
// work as then you would have a permanent port to be dialled.
|
|
148
|
-
// Alas, I struggled to get this to work reliably either. I find there is a race between the
|
|
149
|
-
// service that reads our listener addresses and the uPnP service.
|
|
150
|
-
// The result being the uPnP service can't find an address to use for the port forward.
|
|
151
|
-
// Need to investigate further.
|
|
152
|
-
// if (enableNat) {
|
|
153
|
-
// services.autoNAT = autoNATService({
|
|
154
|
-
// protocolPrefix: 'aztec',
|
|
155
|
-
// });
|
|
156
|
-
// services.uPnPNAT = uPnPNATService();
|
|
157
|
-
// }
|
|
158
|
-
|
|
159
144
|
const node = await createLibp2p({
|
|
160
145
|
start: false,
|
|
161
146
|
peerId,
|
|
@@ -233,14 +218,13 @@ export class LibP2PService implements P2PService {
|
|
|
233
218
|
* @param topic - The message's topic.
|
|
234
219
|
* @param data - The message data
|
|
235
220
|
*/
|
|
236
|
-
private async handleNewGossipMessage(
|
|
237
|
-
if (topic
|
|
238
|
-
|
|
239
|
-
|
|
221
|
+
private async handleNewGossipMessage(message: RawGossipMessage) {
|
|
222
|
+
if (message.topic === Tx.p2pTopic) {
|
|
223
|
+
const tx = Tx.fromBuffer(Buffer.from(message.data));
|
|
224
|
+
await this.processTxFromPeer(tx);
|
|
240
225
|
}
|
|
241
226
|
|
|
242
|
-
|
|
243
|
-
await this.processTxFromPeer(tx);
|
|
227
|
+
return;
|
|
244
228
|
}
|
|
245
229
|
|
|
246
230
|
/**
|
|
@@ -248,7 +232,7 @@ export class LibP2PService implements P2PService {
|
|
|
248
232
|
* @param tx - The transaction to propagate.
|
|
249
233
|
*/
|
|
250
234
|
public propagateTx(tx: Tx): void {
|
|
251
|
-
void this.jobQueue.put(() => Promise.resolve(this.
|
|
235
|
+
void this.jobQueue.put(() => Promise.resolve(this.sendToPeers(tx)));
|
|
252
236
|
}
|
|
253
237
|
|
|
254
238
|
private async processTxFromPeer(tx: Tx): Promise<void> {
|
|
@@ -258,11 +242,14 @@ export class LibP2PService implements P2PService {
|
|
|
258
242
|
await this.txPool.addTxs([tx]);
|
|
259
243
|
}
|
|
260
244
|
|
|
261
|
-
private async
|
|
262
|
-
const
|
|
263
|
-
|
|
264
|
-
const
|
|
265
|
-
this.logger.verbose(`
|
|
245
|
+
private async sendToPeers<T extends Gossipable>(message: T) {
|
|
246
|
+
const parent = message.constructor as typeof Gossipable;
|
|
247
|
+
|
|
248
|
+
const identifier = message.p2pMessageIdentifier().toString();
|
|
249
|
+
this.logger.verbose(`Sending tx ${identifier} to peers`);
|
|
250
|
+
|
|
251
|
+
const recipientsNum = await this.publishToTopic(parent.p2pTopic, message.toBuffer());
|
|
252
|
+
this.logger.verbose(`Sent tx ${identifier} to ${recipientsNum} peers`);
|
|
266
253
|
}
|
|
267
254
|
|
|
268
255
|
// Libp2p seems to hang sometimes if new peers are initiating connections.
|
|
@@ -42,11 +42,17 @@ export class AztecKVTxPool implements TxPool {
|
|
|
42
42
|
|
|
43
43
|
public markAsMined(txHashes: TxHash[]): Promise<void> {
|
|
44
44
|
return this.#store.transaction(() => {
|
|
45
|
+
let deleted = 0;
|
|
45
46
|
for (const hash of txHashes) {
|
|
46
47
|
const key = hash.toString();
|
|
47
48
|
void this.#minedTxs.add(key);
|
|
48
|
-
|
|
49
|
+
if (this.#pendingTxs.has(key)) {
|
|
50
|
+
deleted++;
|
|
51
|
+
void this.#pendingTxs.delete(key);
|
|
52
|
+
}
|
|
49
53
|
}
|
|
54
|
+
this.#metrics.recordRemovedTxs('pending', deleted);
|
|
55
|
+
this.#metrics.recordAddedTxs('mined', txHashes.length);
|
|
50
56
|
});
|
|
51
57
|
}
|
|
52
58
|
|
|
@@ -87,6 +93,7 @@ export class AztecKVTxPool implements TxPool {
|
|
|
87
93
|
public addTxs(txs: Tx[]): Promise<void> {
|
|
88
94
|
const txHashes = txs.map(tx => tx.getTxHash());
|
|
89
95
|
return this.#store.transaction(() => {
|
|
96
|
+
let pendingCount = 0;
|
|
90
97
|
for (const [i, tx] of txs.entries()) {
|
|
91
98
|
const txHash = txHashes[i];
|
|
92
99
|
this.#log.info(`Adding tx with id ${txHash.toString()}`, {
|
|
@@ -97,12 +104,14 @@ export class AztecKVTxPool implements TxPool {
|
|
|
97
104
|
const key = txHash.toString();
|
|
98
105
|
void this.#txs.set(key, tx.toBuffer());
|
|
99
106
|
if (!this.#minedTxs.has(key)) {
|
|
107
|
+
pendingCount++;
|
|
100
108
|
// REFACTOR: Use an lmdb conditional write to avoid race conditions with this write tx
|
|
101
109
|
void this.#pendingTxs.add(key);
|
|
110
|
+
this.#metrics.recordTxSize(tx);
|
|
102
111
|
}
|
|
103
112
|
}
|
|
104
113
|
|
|
105
|
-
this.#metrics.
|
|
114
|
+
this.#metrics.recordAddedTxs('pending', pendingCount);
|
|
106
115
|
});
|
|
107
116
|
}
|
|
108
117
|
|
|
@@ -113,14 +122,24 @@ export class AztecKVTxPool implements TxPool {
|
|
|
113
122
|
*/
|
|
114
123
|
public deleteTxs(txHashes: TxHash[]): Promise<void> {
|
|
115
124
|
return this.#store.transaction(() => {
|
|
125
|
+
let pendingDeleted = 0;
|
|
126
|
+
let minedDeleted = 0;
|
|
116
127
|
for (const hash of txHashes) {
|
|
117
128
|
const key = hash.toString();
|
|
118
129
|
void this.#txs.delete(key);
|
|
119
|
-
|
|
120
|
-
|
|
130
|
+
if (this.#pendingTxs.has(key)) {
|
|
131
|
+
pendingDeleted++;
|
|
132
|
+
void this.#pendingTxs.delete(key);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (this.#minedTxs.has(key)) {
|
|
136
|
+
minedDeleted++;
|
|
137
|
+
void this.#minedTxs.delete(key);
|
|
138
|
+
}
|
|
121
139
|
}
|
|
122
140
|
|
|
123
|
-
this.#metrics.
|
|
141
|
+
this.#metrics.recordRemovedTxs('pending', pendingDeleted);
|
|
142
|
+
this.#metrics.recordRemovedTxs('mined', minedDeleted);
|
|
124
143
|
});
|
|
125
144
|
}
|
|
126
145
|
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { type Tx } from '@aztec/circuit-types';
|
|
2
|
-
import { type Histogram, Metrics, type TelemetryClient, type UpDownCounter } from '@aztec/telemetry-client';
|
|
2
|
+
import { Attributes, type Histogram, Metrics, type TelemetryClient, type UpDownCounter } from '@aztec/telemetry-client';
|
|
3
|
+
|
|
4
|
+
export type TxStatus = 'pending' | 'mined';
|
|
3
5
|
|
|
4
6
|
/**
|
|
5
7
|
* Instrumentation class for the TxPool.
|
|
@@ -33,26 +35,39 @@ export class TxPoolInstrumentation {
|
|
|
33
35
|
});
|
|
34
36
|
}
|
|
35
37
|
|
|
38
|
+
public recordTxSize(tx: Tx) {
|
|
39
|
+
this.txSize.record(tx.getSize());
|
|
40
|
+
}
|
|
41
|
+
|
|
36
42
|
/**
|
|
37
43
|
* Updates the metrics with the new transactions.
|
|
38
44
|
* @param txs - The transactions to record
|
|
39
45
|
*/
|
|
40
|
-
public
|
|
41
|
-
|
|
42
|
-
|
|
46
|
+
public recordAddedTxs(status: string, count = 1) {
|
|
47
|
+
if (count < 0) {
|
|
48
|
+
throw new Error('Count must be positive');
|
|
43
49
|
}
|
|
44
|
-
|
|
45
|
-
|
|
50
|
+
if (count === 0) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
this.txInMempool.add(count, {
|
|
54
|
+
[Attributes.STATUS]: status,
|
|
55
|
+
});
|
|
46
56
|
}
|
|
47
57
|
|
|
48
58
|
/**
|
|
49
59
|
* Updates the metrics by removing transactions from the mempool.
|
|
50
60
|
* @param count - The number of transactions to remove from the mempool
|
|
51
61
|
*/
|
|
52
|
-
public
|
|
62
|
+
public recordRemovedTxs(status: string, count = 1) {
|
|
53
63
|
if (count < 0) {
|
|
54
64
|
throw new Error('Count must be positive');
|
|
55
65
|
}
|
|
56
|
-
|
|
66
|
+
if (count === 0) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
this.txInMempool.add(-1 * count, {
|
|
70
|
+
[Attributes.STATUS]: status,
|
|
71
|
+
});
|
|
57
72
|
}
|
|
58
73
|
}
|
|
@@ -36,6 +36,8 @@ export class InMemoryTxPool implements TxPool {
|
|
|
36
36
|
this.minedTxs.add(key);
|
|
37
37
|
this.pendingTxs.delete(key);
|
|
38
38
|
}
|
|
39
|
+
this.metrics.recordRemovedTxs('pending', txHashes.length);
|
|
40
|
+
this.metrics.recordAddedTxs('mined', txHashes.length);
|
|
39
41
|
return Promise.resolve();
|
|
40
42
|
}
|
|
41
43
|
|
|
@@ -74,7 +76,7 @@ export class InMemoryTxPool implements TxPool {
|
|
|
74
76
|
* @returns Empty promise.
|
|
75
77
|
*/
|
|
76
78
|
public addTxs(txs: Tx[]): Promise<void> {
|
|
77
|
-
|
|
79
|
+
let pending = 0;
|
|
78
80
|
for (const tx of txs) {
|
|
79
81
|
const txHash = tx.getTxHash();
|
|
80
82
|
this.log.debug(`Adding tx with id ${txHash.toString()}`, {
|
|
@@ -85,9 +87,13 @@ export class InMemoryTxPool implements TxPool {
|
|
|
85
87
|
const key = txHash.toBigInt();
|
|
86
88
|
this.txs.set(key, tx);
|
|
87
89
|
if (!this.minedTxs.has(key)) {
|
|
90
|
+
pending++;
|
|
91
|
+
this.metrics.recordTxSize(tx);
|
|
88
92
|
this.pendingTxs.add(key);
|
|
89
93
|
}
|
|
90
94
|
}
|
|
95
|
+
|
|
96
|
+
this.metrics.recordAddedTxs('pending', pending);
|
|
91
97
|
return Promise.resolve();
|
|
92
98
|
}
|
|
93
99
|
|
|
@@ -97,13 +103,19 @@ export class InMemoryTxPool implements TxPool {
|
|
|
97
103
|
* @returns The number of transactions that was deleted from the pool.
|
|
98
104
|
*/
|
|
99
105
|
public deleteTxs(txHashes: TxHash[]): Promise<void> {
|
|
100
|
-
|
|
106
|
+
let deletedMined = 0;
|
|
107
|
+
let deletedPending = 0;
|
|
108
|
+
|
|
101
109
|
for (const txHash of txHashes) {
|
|
102
110
|
const key = txHash.toBigInt();
|
|
103
111
|
this.txs.delete(key);
|
|
104
|
-
this.pendingTxs.delete(key);
|
|
105
|
-
this.minedTxs.delete(key);
|
|
112
|
+
deletedPending += this.pendingTxs.delete(key) ? 1 : 0;
|
|
113
|
+
deletedMined += this.minedTxs.delete(key) ? 1 : 0;
|
|
106
114
|
}
|
|
115
|
+
|
|
116
|
+
this.metrics.recordRemovedTxs('pending', deletedPending);
|
|
117
|
+
this.metrics.recordRemovedTxs('mined', deletedMined);
|
|
118
|
+
|
|
107
119
|
return Promise.resolve();
|
|
108
120
|
}
|
|
109
121
|
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/// <reference types="node" resolution-mode="require"/>
|
|
2
|
-
import { type Tx } from '@aztec/circuit-types';
|
|
3
|
-
import { type SemVer } from 'semver';
|
|
4
|
-
export declare const TX_MESSAGE_TOPIC = "";
|
|
5
|
-
export declare class AztecTxMessageCreator {
|
|
6
|
-
private readonly topic;
|
|
7
|
-
constructor(version: SemVer);
|
|
8
|
-
createTxMessage(tx: Tx): {
|
|
9
|
-
topic: string;
|
|
10
|
-
data: Buffer;
|
|
11
|
-
};
|
|
12
|
-
getTopic(): string;
|
|
13
|
-
}
|
|
14
|
-
//# sourceMappingURL=tx_messages.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tx_messages.d.ts","sourceRoot":"","sources":["../../src/service/tx_messages.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,KAAK,EAAE,EAAE,MAAM,sBAAsB,CAAC;AAE/C,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,QAAQ,CAAC;AAErC,eAAO,MAAM,gBAAgB,KAAK,CAAC;AAEnC,qBAAa,qBAAqB;IAChC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;gBACnB,OAAO,EAAE,MAAM;IAI3B,eAAe,CAAC,EAAE,EAAE,EAAE;;;;IAMtB,QAAQ;CAGT"}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
export const TX_MESSAGE_TOPIC = '';
|
|
2
|
-
export class AztecTxMessageCreator {
|
|
3
|
-
constructor(version) {
|
|
4
|
-
this.topic = `/aztec/tx/${version.toString()}`;
|
|
5
|
-
}
|
|
6
|
-
createTxMessage(tx) {
|
|
7
|
-
const messageData = tx.toBuffer();
|
|
8
|
-
return { topic: this.topic, data: messageData };
|
|
9
|
-
}
|
|
10
|
-
getTopic() {
|
|
11
|
-
return this.topic;
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHhfbWVzc2FnZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc2VydmljZS90eF9tZXNzYWdlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFJQSxNQUFNLENBQUMsTUFBTSxnQkFBZ0IsR0FBRyxFQUFFLENBQUM7QUFFbkMsTUFBTSxPQUFPLHFCQUFxQjtJQUVoQyxZQUFZLE9BQWU7UUFDekIsSUFBSSxDQUFDLEtBQUssR0FBRyxhQUFhLE9BQU8sQ0FBQyxRQUFRLEVBQUUsRUFBRSxDQUFDO0lBQ2pELENBQUM7SUFFRCxlQUFlLENBQUMsRUFBTTtRQUNwQixNQUFNLFdBQVcsR0FBRyxFQUFFLENBQUMsUUFBUSxFQUFFLENBQUM7UUFFbEMsT0FBTyxFQUFFLEtBQUssRUFBRSxJQUFJLENBQUMsS0FBSyxFQUFFLElBQUksRUFBRSxXQUFXLEVBQUUsQ0FBQztJQUNsRCxDQUFDO0lBRUQsUUFBUTtRQUNOLE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQztJQUNwQixDQUFDO0NBQ0YifQ==
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { type Tx } from '@aztec/circuit-types';
|
|
2
|
-
|
|
3
|
-
import { type SemVer } from 'semver';
|
|
4
|
-
|
|
5
|
-
export const TX_MESSAGE_TOPIC = '';
|
|
6
|
-
|
|
7
|
-
export class AztecTxMessageCreator {
|
|
8
|
-
private readonly topic: string;
|
|
9
|
-
constructor(version: SemVer) {
|
|
10
|
-
this.topic = `/aztec/tx/${version.toString()}`;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
createTxMessage(tx: Tx) {
|
|
14
|
-
const messageData = tx.toBuffer();
|
|
15
|
-
|
|
16
|
-
return { topic: this.topic, data: messageData };
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
getTopic() {
|
|
20
|
-
return this.topic;
|
|
21
|
-
}
|
|
22
|
-
}
|