@aztec/p2p 0.42.0 → 0.44.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.
Files changed (59) hide show
  1. package/dest/bootstrap/bootstrap.d.ts +1 -1
  2. package/dest/bootstrap/bootstrap.d.ts.map +1 -1
  3. package/dest/bootstrap/bootstrap.js +8 -4
  4. package/dest/client/index.d.ts.map +1 -1
  5. package/dest/client/index.js +24 -21
  6. package/dest/client/p2p_client.d.ts.map +1 -1
  7. package/dest/client/p2p_client.js +2 -3
  8. package/dest/config.d.ts +9 -22
  9. package/dest/config.d.ts.map +1 -1
  10. package/dest/config.js +8 -9
  11. package/dest/service/discV5_service.d.ts +5 -2
  12. package/dest/service/discV5_service.d.ts.map +1 -1
  13. package/dest/service/discV5_service.js +38 -12
  14. package/dest/service/dummy_service.d.ts +4 -1
  15. package/dest/service/dummy_service.d.ts.map +1 -1
  16. package/dest/service/dummy_service.js +7 -1
  17. package/dest/service/libp2p_service.d.ts +5 -14
  18. package/dest/service/libp2p_service.d.ts.map +1 -1
  19. package/dest/service/libp2p_service.js +56 -97
  20. package/dest/service/peer_manager.d.ts +25 -3
  21. package/dest/service/peer_manager.d.ts.map +1 -1
  22. package/dest/service/peer_manager.js +152 -12
  23. package/dest/service/service.d.ts +12 -6
  24. package/dest/service/service.d.ts.map +1 -1
  25. package/dest/service/service.js +1 -1
  26. package/dest/tx_pool/aztec_kv_tx_pool.d.ts +2 -1
  27. package/dest/tx_pool/aztec_kv_tx_pool.d.ts.map +1 -1
  28. package/dest/tx_pool/aztec_kv_tx_pool.js +11 -6
  29. package/dest/tx_pool/instrumentation.d.ts +23 -0
  30. package/dest/tx_pool/instrumentation.d.ts.map +1 -0
  31. package/dest/tx_pool/instrumentation.js +48 -0
  32. package/dest/tx_pool/memory_tx_pool.d.ts +3 -1
  33. package/dest/tx_pool/memory_tx_pool.d.ts.map +1 -1
  34. package/dest/tx_pool/memory_tx_pool.js +6 -2
  35. package/dest/util.d.ts +21 -0
  36. package/dest/util.d.ts.map +1 -0
  37. package/dest/util.js +59 -0
  38. package/package.json +15 -6
  39. package/src/bootstrap/bootstrap.ts +11 -5
  40. package/src/client/index.ts +28 -21
  41. package/src/client/p2p_client.ts +1 -2
  42. package/src/config.ts +19 -39
  43. package/src/service/discV5_service.ts +45 -15
  44. package/src/service/dummy_service.ts +10 -1
  45. package/src/service/libp2p_service.ts +60 -108
  46. package/src/service/peer_manager.ts +187 -12
  47. package/src/service/service.ts +14 -7
  48. package/src/tx_pool/aztec_kv_tx_pool.ts +12 -3
  49. package/src/tx_pool/instrumentation.ts +58 -0
  50. package/src/tx_pool/memory_tx_pool.ts +8 -1
  51. package/src/util.ts +62 -0
  52. package/dest/service/ip_query.d.ts +0 -2
  53. package/dest/service/ip_query.d.ts.map +0 -1
  54. package/dest/service/ip_query.js +0 -6
  55. package/dest/service/known_txs.d.ts +0 -31
  56. package/dest/service/known_txs.d.ts.map +0 -1
  57. package/dest/service/known_txs.js +0 -52
  58. package/src/service/ip_query.ts +0 -5
  59. package/src/service/known_txs.ts +0 -56
@@ -2,7 +2,9 @@ import { Tx, TxHash } from '@aztec/circuit-types';
2
2
  import { type TxAddedToPoolStats } from '@aztec/circuit-types/stats';
3
3
  import { type Logger, createDebugLogger } from '@aztec/foundation/log';
4
4
  import { type AztecKVStore, type AztecMap } from '@aztec/kv-store';
5
+ import { type TelemetryClient } from '@aztec/telemetry-client';
5
6
 
7
+ import { TxPoolInstrumentation } from './instrumentation.js';
6
8
  import { type TxPool } from './tx_pool.js';
7
9
 
8
10
  /**
@@ -18,15 +20,18 @@ export class AztecKVTxPool implements TxPool {
18
20
 
19
21
  #log: Logger;
20
22
 
23
+ #metrics: TxPoolInstrumentation;
24
+
21
25
  /**
22
26
  * Class constructor for in-memory TxPool. Initiates our transaction pool as a JS Map.
23
27
  * @param store - A KV store.
24
28
  * @param log - A logger.
25
29
  */
26
- constructor(store: AztecKVStore, log = createDebugLogger('aztec:tx_pool')) {
30
+ constructor(store: AztecKVStore, telemetry: TelemetryClient, log = createDebugLogger('aztec:tx_pool')) {
27
31
  this.#txs = store.openMap('txs');
28
32
  this.#store = store;
29
33
  this.#log = log;
34
+ this.#metrics = new TxPoolInstrumentation(telemetry, 'AztecKVTxPool');
30
35
  }
31
36
 
32
37
  /**
@@ -44,8 +49,8 @@ export class AztecKVTxPool implements TxPool {
44
49
  * @param txs - An array of txs to be added to the pool.
45
50
  * @returns Empty promise.
46
51
  */
47
- public async addTxs(txs: Tx[]): Promise<void> {
48
- const txHashes = await Promise.all(txs.map(tx => tx.getTxHash()));
52
+ public addTxs(txs: Tx[]): Promise<void> {
53
+ const txHashes = txs.map(tx => tx.getTxHash());
49
54
  return this.#store.transaction(() => {
50
55
  for (const [i, tx] of txs.entries()) {
51
56
  const txHash = txHashes[i];
@@ -56,6 +61,8 @@ export class AztecKVTxPool implements TxPool {
56
61
 
57
62
  void this.#txs.set(txHash.toString(), tx.toBuffer());
58
63
  }
64
+
65
+ this.#metrics.recordTxs(txs);
59
66
  });
60
67
  }
61
68
 
@@ -69,6 +76,8 @@ export class AztecKVTxPool implements TxPool {
69
76
  for (const hash of txHashes) {
70
77
  void this.#txs.delete(hash.toString());
71
78
  }
79
+
80
+ this.#metrics.removeTxs(txHashes.length);
72
81
  });
73
82
  }
74
83
 
@@ -0,0 +1,58 @@
1
+ import { type Tx } from '@aztec/circuit-types';
2
+ import { type Histogram, Metrics, type TelemetryClient, type UpDownCounter } from '@aztec/telemetry-client';
3
+
4
+ /**
5
+ * Instrumentation class for the TxPool.
6
+ */
7
+ export class TxPoolInstrumentation {
8
+ /** The number of txs in the mempool */
9
+ private txInMempool: UpDownCounter;
10
+ /** Tracks tx size */
11
+ private txSize: Histogram;
12
+
13
+ constructor(telemetry: TelemetryClient, name: string) {
14
+ const meter = telemetry.getMeter(name);
15
+ this.txInMempool = meter.createUpDownCounter(Metrics.MEMPOOL_TX_COUNT, {
16
+ description: 'The current number of transactions in the mempool',
17
+ });
18
+
19
+ this.txSize = meter.createHistogram(Metrics.MEMPOOL_TX_SIZE, {
20
+ unit: 'By',
21
+ description: 'The size of transactions in the mempool',
22
+ advice: {
23
+ explicitBucketBoundaries: [
24
+ 5_000, // 5KB
25
+ 10_000,
26
+ 20_000,
27
+ 50_000,
28
+ 75_000,
29
+ 100_000, // 100KB
30
+ 200_000,
31
+ ],
32
+ },
33
+ });
34
+ }
35
+
36
+ /**
37
+ * Updates the metrics with the new transactions.
38
+ * @param txs - The transactions to record
39
+ */
40
+ public recordTxs(txs: Tx[]) {
41
+ for (const tx of txs) {
42
+ this.txSize.record(tx.getSize());
43
+ }
44
+
45
+ this.txInMempool.add(txs.length);
46
+ }
47
+
48
+ /**
49
+ * Updates the metrics by removing transactions from the mempool.
50
+ * @param count - The number of transactions to remove from the mempool
51
+ */
52
+ public removeTxs(count = 1) {
53
+ if (count < 0) {
54
+ throw new Error('Count must be positive');
55
+ }
56
+ this.txInMempool.add(-1 * count);
57
+ }
58
+ }
@@ -1,7 +1,9 @@
1
1
  import { Tx, TxHash } from '@aztec/circuit-types';
2
2
  import { type TxAddedToPoolStats } from '@aztec/circuit-types/stats';
3
3
  import { createDebugLogger } from '@aztec/foundation/log';
4
+ import { type TelemetryClient } from '@aztec/telemetry-client';
4
5
 
6
+ import { TxPoolInstrumentation } from './instrumentation.js';
5
7
  import { type TxPool } from './tx_pool.js';
6
8
 
7
9
  /**
@@ -13,12 +15,15 @@ export class InMemoryTxPool implements TxPool {
13
15
  */
14
16
  private txs: Map<bigint, Tx>;
15
17
 
18
+ private metrics: TxPoolInstrumentation;
19
+
16
20
  /**
17
21
  * Class constructor for in-memory TxPool. Initiates our transaction pool as a JS Map.
18
22
  * @param log - A logger.
19
23
  */
20
- constructor(private log = createDebugLogger('aztec:tx_pool')) {
24
+ constructor(telemetry: TelemetryClient, private log = createDebugLogger('aztec:tx_pool')) {
21
25
  this.txs = new Map<bigint, Tx>();
26
+ this.metrics = new TxPoolInstrumentation(telemetry, 'InMemoryTxPool');
22
27
  }
23
28
 
24
29
  /**
@@ -37,6 +42,7 @@ export class InMemoryTxPool implements TxPool {
37
42
  * @returns Empty promise.
38
43
  */
39
44
  public addTxs(txs: Tx[]): Promise<void> {
45
+ this.metrics.recordTxs(txs);
40
46
  for (const tx of txs) {
41
47
  const txHash = tx.getTxHash();
42
48
  this.log.debug(`Adding tx with id ${txHash.toString()}`, {
@@ -54,6 +60,7 @@ export class InMemoryTxPool implements TxPool {
54
60
  * @returns The number of transactions that was deleted from the pool.
55
61
  */
56
62
  public deleteTxs(txHashes: TxHash[]): Promise<void> {
63
+ this.metrics.removeTxs(txHashes.length);
57
64
  for (const txHash of txHashes) {
58
65
  this.txs.delete(txHash.toBigInt());
59
66
  }
package/src/util.ts ADDED
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Converts an address string to a multiaddr string.
3
+ * Example usage:
4
+ * const tcpAddr = '123.456.7.8:80' -> /ip4/123.456.7.8/tcp/80
5
+ * const udpAddr = '[2001:db8::1]:8080' -> /ip6/2001:db8::1/udp/8080
6
+ * const dnsAddr = 'example.com:443' -> /dns4/example.com/tcp/443
7
+ * @param address - The address string to convert. Has to be in the format <addr>:<port>.
8
+ * @param protocol - The protocol to use in the multiaddr string.
9
+ * @returns A multiaddr compliant string.
10
+ */
11
+ export function convertToMultiaddr(address: string, protocol: 'tcp' | 'udp'): string {
12
+ const [addr, port] = splitAddressPort(address, false);
13
+
14
+ let multiaddrPrefix: string;
15
+
16
+ if (addr.includes(':')) {
17
+ // IPv6 address
18
+ multiaddrPrefix = 'ip6';
19
+ } else if (addr.match(/^[\d.]+$/)) {
20
+ // IPv4 address
21
+ multiaddrPrefix = 'ip4';
22
+ } else {
23
+ throw new Error('Invalid address format. Expected an IPv4 or IPv6 address.');
24
+ }
25
+
26
+ return `/${multiaddrPrefix}/${addr}/${protocol}/${port}`;
27
+ }
28
+
29
+ /**
30
+ * Splits an <address>:<port> string into its components.
31
+ * @returns The ip6 or ip4 address & port separately
32
+ */
33
+ export function splitAddressPort(address: string, allowEmptyAddress: boolean): [string, string] {
34
+ let addr: string;
35
+ let port: string;
36
+
37
+ if (address.startsWith('[')) {
38
+ // IPv6 address enclosed in square brackets
39
+ const match = address.match(/^\[([^\]]+)\]:(\d+)$/);
40
+ if (!match) {
41
+ throw new Error(`Invalid IPv6 address format:${address}. Expected format: [<addr>]:<port>`);
42
+ }
43
+ [, addr, port] = match;
44
+ } else {
45
+ // IPv4 address
46
+ [addr, port] = address.split(':');
47
+ if ((!addr && !allowEmptyAddress) || !port) {
48
+ throw new Error(`Invalid address format: ${address}. Expected format: <addr>:<port>`);
49
+ }
50
+ }
51
+
52
+ return [addr, port];
53
+ }
54
+
55
+ /**
56
+ * Queries the public IP address of the machine.
57
+ */
58
+ export async function getPublicIp(): Promise<string> {
59
+ const resp = await fetch('http://checkip.amazonaws.com/');
60
+ const text = await resp.text();
61
+ return text.trim();
62
+ }
@@ -1,2 +0,0 @@
1
- export declare function getPublicIp(): Promise<string>;
2
- //# sourceMappingURL=ip_query.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ip_query.d.ts","sourceRoot":"","sources":["../../src/service/ip_query.ts"],"names":[],"mappings":"AAAA,wBAAsB,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC,CAInD"}
@@ -1,6 +0,0 @@
1
- export async function getPublicIp() {
2
- const resp = await fetch('http://checkip.amazonaws.com/');
3
- const text = await resp.text();
4
- return text.trim();
5
- }
6
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaXBfcXVlcnkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc2VydmljZS9pcF9xdWVyeS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxNQUFNLENBQUMsS0FBSyxVQUFVLFdBQVc7SUFDL0IsTUFBTSxJQUFJLEdBQUcsTUFBTSxLQUFLLENBQUMsK0JBQStCLENBQUMsQ0FBQztJQUMxRCxNQUFNLElBQUksR0FBRyxNQUFNLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUMvQixPQUFPLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztBQUNyQixDQUFDIn0=
@@ -1,31 +0,0 @@
1
- import { type PeerId } from '@libp2p/interface';
2
- /**
3
- * Keeps a record of which Peers have 'seen' which transactions.
4
- */
5
- export declare class KnownTxLookup {
6
- private lookup;
7
- constructor();
8
- /**
9
- * Inform this lookup that a peer has 'seen' a transaction.
10
- * @param peerId - The peerId of the peer that has 'seen' the transaction.
11
- * @param txHash - The thHash of the 'seen' transaction.
12
- */
13
- addPeerForTx(peerId: PeerId, txHash: string): void;
14
- /**
15
- * Determine if a peer has 'seen' a transaction.
16
- * @param peerId - The peerId of the peer.
17
- * @param txHash - The thHash of the transaction.
18
- * @returns A boolean indicating if the transaction has been 'seen' by the peer.
19
- */
20
- hasPeerSeenTx(peerId: PeerId, txHash: string): boolean;
21
- /**
22
- * Updates the lookup from the result of settled txs
23
- * These txs will be cleared out of the lookup.
24
- * It is possible that some txs could still be gossiped for a
25
- * short period of time meaning they come back into this lookup
26
- * but this should be infrequent and cause no undesirable effects
27
- * @param txHashes - The hashes of the newly settled transactions
28
- */
29
- handleSettledTxs(txHashes: string[]): void;
30
- }
31
- //# sourceMappingURL=known_txs.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"known_txs.d.ts","sourceRoot":"","sources":["../../src/service/known_txs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAEhD;;GAEG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAqD;;IAInE;;;;OAIG;IACI,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IAYlD;;;;;OAKG;IACI,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IASnD;;;;;;;OAOG;IACI,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE;CAK3C"}
@@ -1,52 +0,0 @@
1
- /**
2
- * Keeps a record of which Peers have 'seen' which transactions.
3
- */
4
- export class KnownTxLookup {
5
- constructor() {
6
- this.lookup = {};
7
- }
8
- /**
9
- * Inform this lookup that a peer has 'seen' a transaction.
10
- * @param peerId - The peerId of the peer that has 'seen' the transaction.
11
- * @param txHash - The thHash of the 'seen' transaction.
12
- */
13
- addPeerForTx(peerId, txHash) {
14
- const peerIdAsString = peerId.toString();
15
- const existingLookup = this.lookup[txHash];
16
- if (existingLookup === undefined) {
17
- const newLookup = {};
18
- newLookup[peerIdAsString] = true;
19
- this.lookup[txHash] = newLookup;
20
- return;
21
- }
22
- existingLookup[peerIdAsString] = true;
23
- }
24
- /**
25
- * Determine if a peer has 'seen' a transaction.
26
- * @param peerId - The peerId of the peer.
27
- * @param txHash - The thHash of the transaction.
28
- * @returns A boolean indicating if the transaction has been 'seen' by the peer.
29
- */
30
- hasPeerSeenTx(peerId, txHash) {
31
- const existingLookup = this.lookup[txHash];
32
- if (existingLookup === undefined) {
33
- return false;
34
- }
35
- const peerIdAsString = peerId.toString();
36
- return !!existingLookup[peerIdAsString];
37
- }
38
- /**
39
- * Updates the lookup from the result of settled txs
40
- * These txs will be cleared out of the lookup.
41
- * It is possible that some txs could still be gossiped for a
42
- * short period of time meaning they come back into this lookup
43
- * but this should be infrequent and cause no undesirable effects
44
- * @param txHashes - The hashes of the newly settled transactions
45
- */
46
- handleSettledTxs(txHashes) {
47
- for (const txHash of txHashes) {
48
- delete this.lookup[txHash];
49
- }
50
- }
51
- }
52
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoia25vd25fdHhzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3NlcnZpY2Uva25vd25fdHhzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUVBOztHQUVHO0FBQ0gsTUFBTSxPQUFPLGFBQWE7SUFHeEI7UUFGUSxXQUFNLEdBQWtELEVBQUUsQ0FBQztJQUVwRCxDQUFDO0lBRWhCOzs7O09BSUc7SUFDSSxZQUFZLENBQUMsTUFBYyxFQUFFLE1BQWM7UUFDaEQsTUFBTSxjQUFjLEdBQUcsTUFBTSxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQ3pDLE1BQU0sY0FBYyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDM0MsSUFBSSxjQUFjLEtBQUssU0FBUyxFQUFFLENBQUM7WUFDakMsTUFBTSxTQUFTLEdBQStCLEVBQUUsQ0FBQztZQUNqRCxTQUFTLENBQUMsY0FBYyxDQUFDLEdBQUcsSUFBSSxDQUFDO1lBQ2pDLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEdBQUcsU0FBUyxDQUFDO1lBQ2hDLE9BQU87UUFDVCxDQUFDO1FBQ0QsY0FBYyxDQUFDLGNBQWMsQ0FBQyxHQUFHLElBQUksQ0FBQztJQUN4QyxDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSSxhQUFhLENBQUMsTUFBYyxFQUFFLE1BQWM7UUFDakQsTUFBTSxjQUFjLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUMzQyxJQUFJLGNBQWMsS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUNqQyxPQUFPLEtBQUssQ0FBQztRQUNmLENBQUM7UUFDRCxNQUFNLGNBQWMsR0FBRyxNQUFNLENBQUMsUUFBUSxFQUFFLENBQUM7UUFDekMsT0FBTyxDQUFDLENBQUMsY0FBYyxDQUFDLGNBQWMsQ0FBQyxDQUFDO0lBQzFDLENBQUM7SUFFRDs7Ozs7OztPQU9HO0lBQ0ksZ0JBQWdCLENBQUMsUUFBa0I7UUFDeEMsS0FBSyxNQUFNLE1BQU0sSUFBSSxRQUFRLEVBQUUsQ0FBQztZQUM5QixPQUFPLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDN0IsQ0FBQztJQUNILENBQUM7Q0FDRiJ9
@@ -1,5 +0,0 @@
1
- export async function getPublicIp(): Promise<string> {
2
- const resp = await fetch('http://checkip.amazonaws.com/');
3
- const text = await resp.text();
4
- return text.trim();
5
- }
@@ -1,56 +0,0 @@
1
- import { type PeerId } from '@libp2p/interface';
2
-
3
- /**
4
- * Keeps a record of which Peers have 'seen' which transactions.
5
- */
6
- export class KnownTxLookup {
7
- private lookup: { [key: string]: { [key: string]: boolean } } = {};
8
-
9
- constructor() {}
10
-
11
- /**
12
- * Inform this lookup that a peer has 'seen' a transaction.
13
- * @param peerId - The peerId of the peer that has 'seen' the transaction.
14
- * @param txHash - The thHash of the 'seen' transaction.
15
- */
16
- public addPeerForTx(peerId: PeerId, txHash: string) {
17
- const peerIdAsString = peerId.toString();
18
- const existingLookup = this.lookup[txHash];
19
- if (existingLookup === undefined) {
20
- const newLookup: { [key: string]: boolean } = {};
21
- newLookup[peerIdAsString] = true;
22
- this.lookup[txHash] = newLookup;
23
- return;
24
- }
25
- existingLookup[peerIdAsString] = true;
26
- }
27
-
28
- /**
29
- * Determine if a peer has 'seen' a transaction.
30
- * @param peerId - The peerId of the peer.
31
- * @param txHash - The thHash of the transaction.
32
- * @returns A boolean indicating if the transaction has been 'seen' by the peer.
33
- */
34
- public hasPeerSeenTx(peerId: PeerId, txHash: string) {
35
- const existingLookup = this.lookup[txHash];
36
- if (existingLookup === undefined) {
37
- return false;
38
- }
39
- const peerIdAsString = peerId.toString();
40
- return !!existingLookup[peerIdAsString];
41
- }
42
-
43
- /**
44
- * Updates the lookup from the result of settled txs
45
- * These txs will be cleared out of the lookup.
46
- * It is possible that some txs could still be gossiped for a
47
- * short period of time meaning they come back into this lookup
48
- * but this should be infrequent and cause no undesirable effects
49
- * @param txHashes - The hashes of the newly settled transactions
50
- */
51
- public handleSettledTxs(txHashes: string[]) {
52
- for (const txHash of txHashes) {
53
- delete this.lookup[txHash];
54
- }
55
- }
56
- }