@aztec/p2p 4.0.0-devnet.1-patch.1 → 4.0.0-devnet.2-patch.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.
- package/dest/client/factory.d.ts +3 -2
- package/dest/client/factory.d.ts.map +1 -1
- package/dest/client/factory.js +9 -5
- package/dest/client/interface.d.ts +8 -8
- package/dest/client/interface.d.ts.map +1 -1
- package/dest/client/p2p_client.d.ts +4 -6
- package/dest/client/p2p_client.d.ts.map +1 -1
- package/dest/client/p2p_client.js +46 -14
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.js +6 -5
- package/dest/config.d.ts +10 -1
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +5 -0
- package/dest/errors/tx-pool.error.d.ts +8 -0
- package/dest/errors/tx-pool.error.d.ts.map +1 -0
- package/dest/errors/tx-pool.error.js +9 -0
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +4 -2
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool.js +5 -0
- package/dest/mem_pools/attestation_pool/mocks.d.ts +2 -2
- 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/eviction/invalid_txs_after_mining_rule.js +3 -3
- package/dest/mem_pools/tx_pool_v2/deleted_pool.d.ts +30 -13
- package/dest/mem_pools/tx_pool_v2/deleted_pool.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/deleted_pool.js +91 -20
- package/dest/mem_pools/tx_pool_v2/eviction/eviction_manager.d.ts +3 -3
- package/dest/mem_pools/tx_pool_v2/eviction/eviction_manager.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/eviction_manager.js +18 -9
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.d.ts +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.js +4 -1
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.d.ts +3 -3
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.js +10 -4
- package/dest/mem_pools/tx_pool_v2/eviction/index.d.ts +2 -2
- package/dest/mem_pools/tx_pool_v2/eviction/index.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/index.js +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/interfaces.d.ts +48 -5
- package/dest/mem_pools/tx_pool_v2/eviction/interfaces.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/interfaces.js +8 -0
- package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.js +7 -5
- package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.js +5 -3
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.d.ts +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.js +8 -4
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.d.ts +4 -4
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.js +14 -4
- package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.d.ts +3 -3
- package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.js +2 -2
- package/dest/mem_pools/tx_pool_v2/instrumentation.d.ts +15 -0
- package/dest/mem_pools/tx_pool_v2/instrumentation.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/instrumentation.js +43 -0
- package/dest/mem_pools/tx_pool_v2/interfaces.d.ts +14 -2
- package/dest/mem_pools/tx_pool_v2/interfaces.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/interfaces.js +3 -1
- package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts +9 -5
- package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_metadata.js +30 -5
- package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts +12 -3
- package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_pool_indices.js +27 -4
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts +8 -3
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2.js +11 -6
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts +12 -4
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.js +164 -37
- package/dest/msg_validators/tx_validator/timestamp_validator.d.ts +2 -2
- package/dest/msg_validators/tx_validator/timestamp_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/timestamp_validator.js +6 -6
- package/dest/services/encoding.d.ts +1 -1
- package/dest/services/encoding.d.ts.map +1 -1
- package/dest/services/encoding.js +2 -1
- package/dest/services/libp2p/libp2p_service.js +2 -2
- package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts +4 -3
- package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts.map +1 -1
- package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.js +5 -9
- package/dest/services/reqresp/batch-tx-requester/interface.d.ts +2 -6
- package/dest/services/reqresp/batch-tx-requester/interface.d.ts.map +1 -1
- package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts +10 -13
- package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts.map +1 -1
- package/dest/services/reqresp/batch-tx-requester/missing_txs.js +25 -46
- package/dest/services/tx_collection/config.d.ts +13 -1
- package/dest/services/tx_collection/config.d.ts.map +1 -1
- package/dest/services/tx_collection/config.js +30 -0
- package/dest/services/tx_collection/fast_tx_collection.d.ts +1 -1
- package/dest/services/tx_collection/fast_tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/fast_tx_collection.js +39 -33
- package/dest/services/tx_collection/file_store_tx_collection.d.ts +38 -29
- package/dest/services/tx_collection/file_store_tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/file_store_tx_collection.js +126 -77
- package/dest/services/tx_collection/file_store_tx_source.d.ts +16 -6
- package/dest/services/tx_collection/file_store_tx_source.d.ts.map +1 -1
- package/dest/services/tx_collection/file_store_tx_source.js +49 -16
- package/dest/services/tx_collection/instrumentation.d.ts +1 -1
- package/dest/services/tx_collection/instrumentation.d.ts.map +1 -1
- package/dest/services/tx_collection/instrumentation.js +2 -1
- package/dest/services/tx_collection/missing_txs_tracker.d.ts +32 -0
- package/dest/services/tx_collection/missing_txs_tracker.d.ts.map +1 -0
- package/dest/services/tx_collection/missing_txs_tracker.js +27 -0
- package/dest/services/tx_collection/proposal_tx_collector.d.ts +7 -6
- package/dest/services/tx_collection/proposal_tx_collector.d.ts.map +1 -1
- package/dest/services/tx_collection/proposal_tx_collector.js +5 -4
- package/dest/services/tx_collection/slow_tx_collection.d.ts +5 -3
- package/dest/services/tx_collection/slow_tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/slow_tx_collection.js +17 -12
- package/dest/services/tx_collection/tx_collection.d.ts +9 -6
- package/dest/services/tx_collection/tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/tx_collection.js +26 -10
- package/dest/services/tx_collection/tx_collection_sink.d.ts +6 -5
- package/dest/services/tx_collection/tx_collection_sink.d.ts.map +1 -1
- package/dest/services/tx_collection/tx_collection_sink.js +13 -22
- package/dest/services/tx_collection/tx_source.d.ts +8 -3
- package/dest/services/tx_collection/tx_source.d.ts.map +1 -1
- package/dest/services/tx_collection/tx_source.js +19 -2
- package/dest/services/tx_file_store/tx_file_store.d.ts +3 -2
- package/dest/services/tx_file_store/tx_file_store.d.ts.map +1 -1
- package/dest/services/tx_file_store/tx_file_store.js +9 -6
- package/dest/test-helpers/testbench-utils.d.ts +7 -2
- package/dest/test-helpers/testbench-utils.d.ts.map +1 -1
- package/dest/test-helpers/testbench-utils.js +7 -1
- package/dest/testbench/p2p_client_testbench_worker.d.ts +2 -2
- package/dest/testbench/p2p_client_testbench_worker.d.ts.map +1 -1
- package/dest/testbench/p2p_client_testbench_worker.js +8 -8
- package/package.json +14 -14
- package/src/client/factory.ts +18 -3
- package/src/client/interface.ts +10 -8
- package/src/client/p2p_client.ts +52 -17
- package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker.ts +18 -8
- package/src/config.ts +8 -0
- package/src/errors/tx-pool.error.ts +12 -0
- package/src/mem_pools/attestation_pool/attestation_pool.ts +8 -0
- package/src/mem_pools/attestation_pool/mocks.ts +2 -1
- package/src/mem_pools/tx_pool/README.md +1 -1
- package/src/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.ts +3 -3
- package/src/mem_pools/tx_pool_v2/README.md +43 -27
- package/src/mem_pools/tx_pool_v2/deleted_pool.ts +109 -22
- package/src/mem_pools/tx_pool_v2/eviction/eviction_manager.ts +21 -8
- package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.ts +4 -1
- package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.ts +15 -4
- package/src/mem_pools/tx_pool_v2/eviction/index.ts +4 -0
- package/src/mem_pools/tx_pool_v2/eviction/interfaces.ts +49 -4
- package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.ts +5 -5
- package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.ts +3 -3
- package/src/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.ts +8 -7
- package/src/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.ts +24 -6
- package/src/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.ts +3 -3
- package/src/mem_pools/tx_pool_v2/instrumentation.ts +69 -0
- package/src/mem_pools/tx_pool_v2/interfaces.ts +14 -2
- package/src/mem_pools/tx_pool_v2/tx_metadata.ts +44 -9
- package/src/mem_pools/tx_pool_v2/tx_pool_indices.ts +32 -5
- package/src/mem_pools/tx_pool_v2/tx_pool_v2.ts +17 -6
- package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +186 -29
- package/src/msg_validators/tx_validator/timestamp_validator.ts +7 -7
- package/src/services/encoding.ts +2 -1
- package/src/services/libp2p/libp2p_service.ts +2 -2
- package/src/services/reqresp/batch-tx-requester/batch_tx_requester.ts +6 -6
- package/src/services/reqresp/batch-tx-requester/interface.ts +1 -5
- package/src/services/reqresp/batch-tx-requester/missing_txs.ts +23 -71
- package/src/services/tx_collection/config.ts +42 -0
- package/src/services/tx_collection/fast_tx_collection.ts +51 -30
- package/src/services/tx_collection/file_store_tx_collection.ts +143 -93
- package/src/services/tx_collection/file_store_tx_source.ts +64 -17
- package/src/services/tx_collection/instrumentation.ts +7 -1
- package/src/services/tx_collection/missing_txs_tracker.ts +52 -0
- package/src/services/tx_collection/proposal_tx_collector.ts +8 -7
- package/src/services/tx_collection/slow_tx_collection.ts +17 -13
- package/src/services/tx_collection/tx_collection.ts +45 -14
- package/src/services/tx_collection/tx_collection_sink.ts +15 -29
- package/src/services/tx_collection/tx_source.ts +22 -3
- package/src/services/tx_file_store/tx_file_store.ts +6 -4
- package/src/test-helpers/testbench-utils.ts +10 -2
- package/src/testbench/p2p_client_testbench_worker.ts +20 -13
|
@@ -1,44 +1,53 @@
|
|
|
1
1
|
import { type Logger } from '@aztec/foundation/log';
|
|
2
|
+
import { DateProvider } from '@aztec/foundation/timer';
|
|
2
3
|
import { Tx, TxHash } from '@aztec/stdlib/tx';
|
|
3
4
|
import type { FileStoreTxSource } from './file_store_tx_source.js';
|
|
4
5
|
import type { TxAddContext, TxCollectionSink } from './tx_collection_sink.js';
|
|
6
|
+
/** Configuration for a FileStoreTxCollection instance. */
|
|
7
|
+
export type FileStoreCollectionConfig = {
|
|
8
|
+
workerCount: number;
|
|
9
|
+
backoffBaseMs: number;
|
|
10
|
+
backoffMaxMs: number;
|
|
11
|
+
};
|
|
5
12
|
/**
|
|
6
13
|
* Collects txs from file stores as a fallback after P2P methods have been tried.
|
|
7
|
-
*
|
|
8
|
-
*
|
|
14
|
+
* Uses a shared worker pool that pulls entries with priority (fewest attempts first),
|
|
15
|
+
* retries with round-robin across sources, and applies exponential backoff between
|
|
16
|
+
* full cycles through all sources.
|
|
9
17
|
*/
|
|
10
18
|
export declare class FileStoreTxCollection {
|
|
11
|
-
private readonly
|
|
19
|
+
private readonly sources;
|
|
12
20
|
private readonly txCollectionSink;
|
|
21
|
+
private readonly config;
|
|
22
|
+
private readonly dateProvider;
|
|
13
23
|
private readonly log;
|
|
14
|
-
/** Map from tx hash to
|
|
15
|
-
private
|
|
16
|
-
/**
|
|
17
|
-
* Tracks tx hashes found elsewhere, even before startCollecting is called.
|
|
18
|
-
* Needed because the orchestrator delays startCollecting via a real sleep, but foundTxs
|
|
19
|
-
* may arrive during that delay — before the hashes are added to pendingTxs.
|
|
20
|
-
*/
|
|
21
|
-
private foundTxHashes;
|
|
22
|
-
/** Queue of tx hashes to be downloaded. */
|
|
23
|
-
private downloadQueue;
|
|
24
|
-
/** Worker promises for concurrent downloads. */
|
|
24
|
+
/** Map from tx hash string to entry for all pending downloads. */
|
|
25
|
+
private entries;
|
|
26
|
+
/** Worker promises for the shared worker pool. */
|
|
25
27
|
private workers;
|
|
26
|
-
/** Whether the
|
|
27
|
-
private
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
/** Whether the worker pool is running. */
|
|
29
|
+
private running;
|
|
30
|
+
/** Signal used to wake sleeping workers when new entries arrive or stop is called. */
|
|
31
|
+
private wakeSignal;
|
|
32
|
+
constructor(sources: FileStoreTxSource[], txCollectionSink: TxCollectionSink, config: FileStoreCollectionConfig, dateProvider?: DateProvider, log?: Logger);
|
|
33
|
+
/** Starts the shared worker pool. */
|
|
30
34
|
start(): void;
|
|
31
|
-
/** Stops all
|
|
35
|
+
/** Stops all workers and clears state. */
|
|
32
36
|
stop(): Promise<void>;
|
|
33
|
-
/**
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
clearPending(): void;
|
|
37
|
-
/** Queue the given tx hashes for file store collection. */
|
|
38
|
-
startCollecting(txHashes: TxHash[], context: TxAddContext): void;
|
|
39
|
-
/** Stop tracking txs that were found elsewhere. */
|
|
37
|
+
/** Adds entries to the shared map and wakes workers. */
|
|
38
|
+
startCollecting(txHashes: TxHash[], context: TxAddContext, deadline: Date): void;
|
|
39
|
+
/** Removes entries for txs that have been found elsewhere. */
|
|
40
40
|
foundTxs(txs: Tx[]): void;
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
/** Clears all pending entries. */
|
|
42
|
+
clearPending(): void;
|
|
43
|
+
private workerLoop;
|
|
44
|
+
/** Single-pass scan: removes expired entries, finds the best ready entry, or computes sleep time. */
|
|
45
|
+
private getNextAction;
|
|
46
|
+
/** Computes backoff for an entry. Backoff applies after a full cycle through all sources. */
|
|
47
|
+
private getBackoffMs;
|
|
48
|
+
/** Resolves the current wake signal and creates a new one. */
|
|
49
|
+
private wake;
|
|
50
|
+
private waitForWake;
|
|
51
|
+
private sleepOrWake;
|
|
43
52
|
}
|
|
44
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
53
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmlsZV9zdG9yZV90eF9jb2xsZWN0aW9uLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvc2VydmljZXMvdHhfY29sbGVjdGlvbi9maWxlX3N0b3JlX3R4X2NvbGxlY3Rpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLEtBQUssTUFBTSxFQUFnQixNQUFNLHVCQUF1QixDQUFDO0FBR2xFLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUN2RCxPQUFPLEVBQUUsRUFBRSxFQUFFLE1BQU0sRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBRTlDLE9BQU8sS0FBSyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDbkUsT0FBTyxLQUFLLEVBQUUsWUFBWSxFQUFFLGdCQUFnQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFFOUUsMERBQTBEO0FBQzFELE1BQU0sTUFBTSx5QkFBeUIsR0FBRztJQUN0QyxXQUFXLEVBQUUsTUFBTSxDQUFDO0lBQ3BCLGFBQWEsRUFBRSxNQUFNLENBQUM7SUFDdEIsWUFBWSxFQUFFLE1BQU0sQ0FBQztDQUN0QixDQUFDO0FBV0Y7Ozs7O0dBS0c7QUFDSCxxQkFBYSxxQkFBcUI7SUFjOUIsT0FBTyxDQUFDLFFBQVEsQ0FBQyxPQUFPO0lBQ3hCLE9BQU8sQ0FBQyxRQUFRLENBQUMsZ0JBQWdCO0lBQ2pDLE9BQU8sQ0FBQyxRQUFRLENBQUMsTUFBTTtJQUN2QixPQUFPLENBQUMsUUFBUSxDQUFDLFlBQVk7SUFDN0IsT0FBTyxDQUFDLFFBQVEsQ0FBQyxHQUFHO0lBakJ0QixrRUFBa0U7SUFDbEUsT0FBTyxDQUFDLE9BQU8sQ0FBdUM7SUFFdEQsa0RBQWtEO0lBQ2xELE9BQU8sQ0FBQyxPQUFPLENBQXVCO0lBRXRDLDBDQUEwQztJQUMxQyxPQUFPLENBQUMsT0FBTyxDQUFTO0lBRXhCLHNGQUFzRjtJQUN0RixPQUFPLENBQUMsVUFBVSxDQUE2QjtJQUUvQyxZQUNtQixPQUFPLEVBQUUsaUJBQWlCLEVBQUUsRUFDNUIsZ0JBQWdCLEVBQUUsZ0JBQWdCLEVBQ2xDLE1BQU0sRUFBRSx5QkFBeUIsRUFDakMsWUFBWSxHQUFFLFlBQWlDLEVBQy9DLEdBQUcsR0FBRSxNQUFxRCxFQUc1RTtJQUVELHFDQUFxQztJQUM5QixLQUFLLElBQUksSUFBSSxDQVNuQjtJQUVELDBDQUEwQztJQUM3QixJQUFJLElBQUksT0FBTyxDQUFDLElBQUksQ0FBQyxDQU1qQztJQUVELHdEQUF3RDtJQUNqRCxlQUFlLENBQUMsUUFBUSxFQUFFLE1BQU0sRUFBRSxFQUFFLE9BQU8sRUFBRSxZQUFZLEVBQUUsUUFBUSxFQUFFLElBQUksR0FBRyxJQUFJLENBc0J0RjtJQUVELDhEQUE4RDtJQUN2RCxRQUFRLENBQUMsR0FBRyxFQUFFLEVBQUUsRUFBRSxHQUFHLElBQUksQ0FJL0I7SUFFRCxrQ0FBa0M7SUFDM0IsWUFBWSxJQUFJLElBQUksQ0FFMUI7WUFFYSxVQUFVO0lBa0N4QixxR0FBcUc7SUFDckcsT0FBTyxDQUFDLGFBQWE7SUE4QnJCLDZGQUE2RjtJQUM3RixPQUFPLENBQUMsWUFBWTtJQVFwQiw4REFBOEQ7SUFDOUQsT0FBTyxDQUFDLElBQUk7WUFNRSxXQUFXO1lBS1gsV0FBVztDQUcxQiJ9
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file_store_tx_collection.d.ts","sourceRoot":"","sources":["../../../src/services/tx_collection/file_store_tx_collection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAgB,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"file_store_tx_collection.d.ts","sourceRoot":"","sources":["../../../src/services/tx_collection/file_store_tx_collection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAgB,MAAM,uBAAuB,CAAC;AAGlE,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE9C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAE9E,0DAA0D;AAC1D,MAAM,MAAM,yBAAyB,GAAG;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAWF;;;;;GAKG;AACH,qBAAa,qBAAqB;IAc9B,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IACjC,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,GAAG;IAjBtB,kEAAkE;IAClE,OAAO,CAAC,OAAO,CAAuC;IAEtD,kDAAkD;IAClD,OAAO,CAAC,OAAO,CAAuB;IAEtC,0CAA0C;IAC1C,OAAO,CAAC,OAAO,CAAS;IAExB,sFAAsF;IACtF,OAAO,CAAC,UAAU,CAA6B;IAE/C,YACmB,OAAO,EAAE,iBAAiB,EAAE,EAC5B,gBAAgB,EAAE,gBAAgB,EAClC,MAAM,EAAE,yBAAyB,EACjC,YAAY,GAAE,YAAiC,EAC/C,GAAG,GAAE,MAAqD,EAG5E;IAED,qCAAqC;IAC9B,KAAK,IAAI,IAAI,CASnB;IAED,0CAA0C;IAC7B,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAMjC;IAED,wDAAwD;IACjD,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,IAAI,GAAG,IAAI,CAsBtF;IAED,8DAA8D;IACvD,QAAQ,CAAC,GAAG,EAAE,EAAE,EAAE,GAAG,IAAI,CAI/B;IAED,kCAAkC;IAC3B,YAAY,IAAI,IAAI,CAE1B;YAEa,UAAU;IAkCxB,qGAAqG;IACrG,OAAO,CAAC,aAAa;IA8BrB,6FAA6F;IAC7F,OAAO,CAAC,YAAY;IAQpB,8DAA8D;IAC9D,OAAO,CAAC,IAAI;YAME,WAAW;YAKX,WAAW;CAG1B"}
|
|
@@ -1,118 +1,167 @@
|
|
|
1
1
|
import { createLogger } from '@aztec/foundation/log';
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
import { promiseWithResolvers } from '@aztec/foundation/promise';
|
|
3
|
+
import { sleep } from '@aztec/foundation/sleep';
|
|
4
|
+
import { DateProvider } from '@aztec/foundation/timer';
|
|
5
|
+
import { TxHash } from '@aztec/stdlib/tx';
|
|
5
6
|
/**
|
|
6
7
|
* Collects txs from file stores as a fallback after P2P methods have been tried.
|
|
7
|
-
*
|
|
8
|
-
*
|
|
8
|
+
* Uses a shared worker pool that pulls entries with priority (fewest attempts first),
|
|
9
|
+
* retries with round-robin across sources, and applies exponential backoff between
|
|
10
|
+
* full cycles through all sources.
|
|
9
11
|
*/ export class FileStoreTxCollection {
|
|
10
|
-
|
|
12
|
+
sources;
|
|
11
13
|
txCollectionSink;
|
|
14
|
+
config;
|
|
15
|
+
dateProvider;
|
|
12
16
|
log;
|
|
13
|
-
/** Map from tx hash to
|
|
14
|
-
/**
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
/** Queue of tx hashes to be downloaded. */ downloadQueue;
|
|
20
|
-
/** Worker promises for concurrent downloads. */ workers;
|
|
21
|
-
/** Whether the collection has been started. */ started;
|
|
22
|
-
constructor(fileStoreSources, txCollectionSink, log = createLogger('p2p:file_store_tx_collection')){
|
|
23
|
-
this.fileStoreSources = fileStoreSources;
|
|
17
|
+
/** Map from tx hash string to entry for all pending downloads. */ entries;
|
|
18
|
+
/** Worker promises for the shared worker pool. */ workers;
|
|
19
|
+
/** Whether the worker pool is running. */ running;
|
|
20
|
+
/** Signal used to wake sleeping workers when new entries arrive or stop is called. */ wakeSignal;
|
|
21
|
+
constructor(sources, txCollectionSink, config, dateProvider = new DateProvider(), log = createLogger('p2p:file_store_tx_collection')){
|
|
22
|
+
this.sources = sources;
|
|
24
23
|
this.txCollectionSink = txCollectionSink;
|
|
24
|
+
this.config = config;
|
|
25
|
+
this.dateProvider = dateProvider;
|
|
25
26
|
this.log = log;
|
|
26
|
-
this.
|
|
27
|
-
this.foundTxHashes = new Set();
|
|
28
|
-
this.downloadQueue = new FifoMemoryQueue();
|
|
27
|
+
this.entries = new Map();
|
|
29
28
|
this.workers = [];
|
|
30
|
-
this.
|
|
29
|
+
this.running = false;
|
|
30
|
+
this.wakeSignal = promiseWithResolvers();
|
|
31
31
|
}
|
|
32
|
-
/** Starts the
|
|
33
|
-
if (this.
|
|
34
|
-
this.log.debug('No file store sources configured
|
|
32
|
+
/** Starts the shared worker pool. */ start() {
|
|
33
|
+
if (this.sources.length === 0) {
|
|
34
|
+
this.log.debug('No file store sources configured');
|
|
35
35
|
return;
|
|
36
36
|
}
|
|
37
|
-
this.
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
for(let i = 0; i < FILE_STORE_DOWNLOAD_CONCURRENCY; i++){
|
|
41
|
-
this.workers.push(this.downloadQueue.process((txHash)=>this.processDownload(txHash)));
|
|
37
|
+
this.running = true;
|
|
38
|
+
for(let i = 0; i < this.config.workerCount; i++){
|
|
39
|
+
this.workers.push(this.workerLoop());
|
|
42
40
|
}
|
|
43
|
-
this.log.info(`Started file store tx collection with ${this.fileStoreSources.length} sources`, {
|
|
44
|
-
sources: this.fileStoreSources.map((s)=>s.getInfo()),
|
|
45
|
-
concurrency: FILE_STORE_DOWNLOAD_CONCURRENCY
|
|
46
|
-
});
|
|
47
41
|
}
|
|
48
|
-
/** Stops all
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}
|
|
52
|
-
this.started = false;
|
|
53
|
-
this.downloadQueue.end();
|
|
42
|
+
/** Stops all workers and clears state. */ async stop() {
|
|
43
|
+
this.running = false;
|
|
44
|
+
this.wake();
|
|
54
45
|
await Promise.all(this.workers);
|
|
55
46
|
this.workers = [];
|
|
56
|
-
this.
|
|
57
|
-
this.foundTxHashes.clear();
|
|
47
|
+
this.entries.clear();
|
|
58
48
|
}
|
|
59
|
-
/**
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
49
|
+
/** Adds entries to the shared map and wakes workers. */ startCollecting(txHashes, context, deadline) {
|
|
50
|
+
if (this.sources.length === 0 || txHashes.length === 0) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
if (+deadline <= this.dateProvider.now()) {
|
|
54
|
+
return;
|
|
63
55
|
}
|
|
64
|
-
}
|
|
65
|
-
/** Clears all pending state. Items already in the download queue will still be processed but won't be re-queued. */ clearPending() {
|
|
66
|
-
this.pendingTxs.clear();
|
|
67
|
-
this.foundTxHashes.clear();
|
|
68
|
-
}
|
|
69
|
-
/** Queue the given tx hashes for file store collection. */ startCollecting(txHashes, context) {
|
|
70
56
|
for (const txHash of txHashes){
|
|
71
57
|
const hashStr = txHash.toString();
|
|
72
|
-
if (!this.
|
|
73
|
-
this.
|
|
74
|
-
|
|
58
|
+
if (!this.entries.has(hashStr)) {
|
|
59
|
+
this.entries.set(hashStr, {
|
|
60
|
+
txHash: hashStr,
|
|
61
|
+
context,
|
|
62
|
+
deadline,
|
|
63
|
+
attempts: 0,
|
|
64
|
+
lastAttemptTime: 0,
|
|
65
|
+
nextSourceIndex: Math.floor(Math.random() * this.sources.length)
|
|
66
|
+
});
|
|
75
67
|
}
|
|
76
68
|
}
|
|
69
|
+
this.wake();
|
|
77
70
|
}
|
|
78
|
-
/**
|
|
71
|
+
/** Removes entries for txs that have been found elsewhere. */ foundTxs(txs) {
|
|
79
72
|
for (const tx of txs){
|
|
80
|
-
|
|
81
|
-
this.pendingTxs.delete(hashStr);
|
|
82
|
-
this.foundTxHashes.add(hashStr);
|
|
73
|
+
this.entries.delete(tx.getTxHash().toString());
|
|
83
74
|
}
|
|
84
75
|
}
|
|
85
|
-
/**
|
|
86
|
-
|
|
87
|
-
const context = this.pendingTxs.get(hashStr);
|
|
88
|
-
// Skip if already found by another method
|
|
89
|
-
if (!context) {
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
92
|
-
await this.downloadTx(txHash, context);
|
|
93
|
-
this.pendingTxs.delete(hashStr);
|
|
76
|
+
/** Clears all pending entries. */ clearPending() {
|
|
77
|
+
this.entries.clear();
|
|
94
78
|
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
79
|
+
async workerLoop() {
|
|
80
|
+
while(this.running){
|
|
81
|
+
const action = this.getNextAction();
|
|
82
|
+
if (action.type === 'sleep') {
|
|
83
|
+
await action.promise;
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
const entry = action.entry;
|
|
87
|
+
const source = this.sources[entry.nextSourceIndex % this.sources.length];
|
|
88
|
+
entry.nextSourceIndex++;
|
|
89
|
+
entry.attempts++;
|
|
90
|
+
entry.lastAttemptTime = this.dateProvider.now();
|
|
99
91
|
try {
|
|
100
|
-
const result = await this.txCollectionSink.collect((
|
|
101
|
-
|
|
92
|
+
const result = await this.txCollectionSink.collect(()=>source.getTxsByHash([
|
|
93
|
+
TxHash.fromString(entry.txHash)
|
|
94
|
+
]), [
|
|
95
|
+
entry.txHash
|
|
102
96
|
], {
|
|
103
97
|
description: `file-store ${source.getInfo()}`,
|
|
104
98
|
method: 'file-store',
|
|
105
99
|
fileStore: source.getInfo()
|
|
106
|
-
}, context);
|
|
100
|
+
}, entry.context);
|
|
107
101
|
if (result.txs.length > 0) {
|
|
108
|
-
|
|
102
|
+
this.entries.delete(entry.txHash);
|
|
109
103
|
}
|
|
110
104
|
} catch (err) {
|
|
111
|
-
this.log.trace(`
|
|
105
|
+
this.log.trace(`Error downloading tx ${entry.txHash} from ${source.getInfo()}`, {
|
|
112
106
|
err
|
|
113
107
|
});
|
|
114
108
|
}
|
|
115
109
|
}
|
|
116
|
-
|
|
110
|
+
}
|
|
111
|
+
/** Single-pass scan: removes expired entries, finds the best ready entry, or computes sleep time. */ getNextAction() {
|
|
112
|
+
const now = this.dateProvider.now();
|
|
113
|
+
let best;
|
|
114
|
+
let earliestReadyAt = Infinity;
|
|
115
|
+
for (const [key, entry] of this.entries){
|
|
116
|
+
if (+entry.deadline <= now) {
|
|
117
|
+
this.entries.delete(key);
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
const backoffMs = this.getBackoffMs(entry);
|
|
121
|
+
const readyAt = entry.lastAttemptTime + backoffMs;
|
|
122
|
+
if (readyAt > now) {
|
|
123
|
+
earliestReadyAt = Math.min(earliestReadyAt, readyAt);
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
if (!best || entry.attempts < best.attempts) {
|
|
127
|
+
best = entry;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
if (best) {
|
|
131
|
+
return {
|
|
132
|
+
type: 'process',
|
|
133
|
+
entry: best
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
if (earliestReadyAt < Infinity) {
|
|
137
|
+
return {
|
|
138
|
+
type: 'sleep',
|
|
139
|
+
promise: this.sleepOrWake(earliestReadyAt - now)
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
return {
|
|
143
|
+
type: 'sleep',
|
|
144
|
+
promise: this.waitForWake()
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
/** Computes backoff for an entry. Backoff applies after a full cycle through all sources. */ getBackoffMs(entry) {
|
|
148
|
+
const fullCycles = Math.floor(entry.attempts / this.sources.length);
|
|
149
|
+
if (fullCycles === 0) {
|
|
150
|
+
return 0;
|
|
151
|
+
}
|
|
152
|
+
return Math.min(this.config.backoffBaseMs * Math.pow(2, fullCycles - 1), this.config.backoffMaxMs);
|
|
153
|
+
}
|
|
154
|
+
/** Resolves the current wake signal and creates a new one. */ wake() {
|
|
155
|
+
this.wakeSignal.resolve();
|
|
156
|
+
this.wakeSignal = promiseWithResolvers();
|
|
157
|
+
}
|
|
158
|
+
/** Waits until the wake signal is resolved. */ async waitForWake() {
|
|
159
|
+
await this.wakeSignal.promise;
|
|
160
|
+
}
|
|
161
|
+
/** Sleeps for the given duration or until the wake signal is resolved. */ async sleepOrWake(ms) {
|
|
162
|
+
await Promise.race([
|
|
163
|
+
sleep(ms),
|
|
164
|
+
this.wakeSignal.promise
|
|
165
|
+
]);
|
|
117
166
|
}
|
|
118
167
|
}
|
|
@@ -1,27 +1,37 @@
|
|
|
1
1
|
import { type Logger } from '@aztec/foundation/log';
|
|
2
|
-
import {
|
|
3
|
-
import type
|
|
2
|
+
import { type TxHash } from '@aztec/stdlib/tx';
|
|
3
|
+
import { type TelemetryClient } from '@aztec/telemetry-client';
|
|
4
|
+
import type { TxSource, TxSourceCollectionResult } from './tx_source.js';
|
|
4
5
|
/** TxSource implementation that downloads txs from a file store. */
|
|
5
6
|
export declare class FileStoreTxSource implements TxSource {
|
|
6
7
|
private readonly fileStore;
|
|
7
8
|
private readonly baseUrl;
|
|
9
|
+
private readonly basePath;
|
|
8
10
|
private readonly log;
|
|
11
|
+
private downloadsSuccess;
|
|
12
|
+
private downloadsFailed;
|
|
13
|
+
private downloadDuration;
|
|
14
|
+
private downloadSize;
|
|
9
15
|
private constructor();
|
|
10
16
|
/**
|
|
11
17
|
* Creates a FileStoreTxSource from a URL.
|
|
12
18
|
* @param url - The file store URL (s3://, gs://, file://, http://, https://).
|
|
19
|
+
* @param basePath - Base path for tx files within the store.
|
|
13
20
|
* @param log - Optional logger.
|
|
21
|
+
* @param telemetry - Optional telemetry client.
|
|
14
22
|
* @returns The FileStoreTxSource instance, or undefined if creation fails.
|
|
15
23
|
*/
|
|
16
|
-
static create(url: string, log?: Logger): Promise<FileStoreTxSource | undefined>;
|
|
24
|
+
static create(url: string, basePath: string, log?: Logger, telemetry?: TelemetryClient): Promise<FileStoreTxSource | undefined>;
|
|
17
25
|
getInfo(): string;
|
|
18
|
-
getTxsByHash(txHashes: TxHash[]): Promise<
|
|
26
|
+
getTxsByHash(txHashes: TxHash[]): Promise<TxSourceCollectionResult>;
|
|
19
27
|
}
|
|
20
28
|
/**
|
|
21
29
|
* Creates FileStoreTxSource instances from URLs.
|
|
22
30
|
* @param urls - Array of file store URLs.
|
|
31
|
+
* @param basePath - Base path for tx files within each store.
|
|
23
32
|
* @param log - Optional logger.
|
|
33
|
+
* @param telemetry - Optional telemetry client.
|
|
24
34
|
* @returns Array of successfully created FileStoreTxSource instances.
|
|
25
35
|
*/
|
|
26
|
-
export declare function createFileStoreTxSources(urls: string[], log?: Logger): Promise<FileStoreTxSource[]>;
|
|
27
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
36
|
+
export declare function createFileStoreTxSources(urls: string[], basePath: string, log?: Logger, telemetry?: TelemetryClient): Promise<FileStoreTxSource[]>;
|
|
37
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmlsZV9zdG9yZV90eF9zb3VyY2UuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9zZXJ2aWNlcy90eF9jb2xsZWN0aW9uL2ZpbGVfc3RvcmVfdHhfc291cmNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxLQUFLLE1BQU0sRUFBZ0IsTUFBTSx1QkFBdUIsQ0FBQztBQUdsRSxPQUFPLEVBQU0sS0FBSyxNQUFNLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUNuRCxPQUFPLEVBR0wsS0FBSyxlQUFlLEVBR3JCLE1BQU0seUJBQXlCLENBQUM7QUFFakMsT0FBTyxLQUFLLEVBQUUsUUFBUSxFQUFFLHdCQUF3QixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFekUsb0VBQW9FO0FBQ3BFLHFCQUFhLGlCQUFrQixZQUFXLFFBQVE7SUFPOUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxTQUFTO0lBQzFCLE9BQU8sQ0FBQyxRQUFRLENBQUMsT0FBTztJQUN4QixPQUFPLENBQUMsUUFBUSxDQUFDLFFBQVE7SUFDekIsT0FBTyxDQUFDLFFBQVEsQ0FBQyxHQUFHO0lBVHRCLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBZ0I7SUFDeEMsT0FBTyxDQUFDLGVBQWUsQ0FBZ0I7SUFDdkMsT0FBTyxDQUFDLGdCQUFnQixDQUFZO0lBQ3BDLE9BQU8sQ0FBQyxZQUFZLENBQVk7SUFFaEMsT0FBTyxlQVlOO0lBRUQ7Ozs7Ozs7T0FPRztJQUNILE9BQW9CLE1BQU0sQ0FDeEIsR0FBRyxFQUFFLE1BQU0sRUFDWCxRQUFRLEVBQUUsTUFBTSxFQUNoQixHQUFHLEdBQUUsTUFBaUQsRUFDdEQsU0FBUyxHQUFFLGVBQXNDLEdBQ2hELE9BQU8sQ0FBQyxpQkFBaUIsR0FBRyxTQUFTLENBQUMsQ0FZeEM7SUFFTSxPQUFPLElBQUksTUFBTSxDQUV2QjtJQUVZLFlBQVksQ0FBQyxRQUFRLEVBQUUsTUFBTSxFQUFFLEdBQUcsT0FBTyxDQUFDLHdCQUF3QixDQUFDLENBK0IvRTtDQUNGO0FBRUQ7Ozs7Ozs7R0FPRztBQUNILHdCQUFzQix3QkFBd0IsQ0FDNUMsSUFBSSxFQUFFLE1BQU0sRUFBRSxFQUNkLFFBQVEsRUFBRSxNQUFNLEVBQ2hCLEdBQUcsR0FBRSxNQUFpRCxFQUN0RCxTQUFTLEdBQUUsZUFBc0MsR0FDaEQsT0FBTyxDQUFDLGlCQUFpQixFQUFFLENBQUMsQ0FHOUIifQ==
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file_store_tx_source.d.ts","sourceRoot":"","sources":["../../../src/services/tx_collection/file_store_tx_source.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAgB,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"file_store_tx_source.d.ts","sourceRoot":"","sources":["../../../src/services/tx_collection/file_store_tx_source.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAgB,MAAM,uBAAuB,CAAC;AAGlE,OAAO,EAAM,KAAK,MAAM,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAGL,KAAK,eAAe,EAGrB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,KAAK,EAAE,QAAQ,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAEzE,oEAAoE;AACpE,qBAAa,iBAAkB,YAAW,QAAQ;IAO9C,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,GAAG;IATtB,OAAO,CAAC,gBAAgB,CAAgB;IACxC,OAAO,CAAC,eAAe,CAAgB;IACvC,OAAO,CAAC,gBAAgB,CAAY;IACpC,OAAO,CAAC,YAAY,CAAY;IAEhC,OAAO,eAYN;IAED;;;;;;;OAOG;IACH,OAAoB,MAAM,CACxB,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,MAAM,EAChB,GAAG,GAAE,MAAiD,EACtD,SAAS,GAAE,eAAsC,GAChD,OAAO,CAAC,iBAAiB,GAAG,SAAS,CAAC,CAYxC;IAEM,OAAO,IAAI,MAAM,CAEvB;IAEY,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,wBAAwB,CAAC,CA+B/E;CACF;AAED;;;;;;;GAOG;AACH,wBAAsB,wBAAwB,CAC5C,IAAI,EAAE,MAAM,EAAE,EACd,QAAQ,EAAE,MAAM,EAChB,GAAG,GAAE,MAAiD,EACtD,SAAS,GAAE,eAAsC,GAChD,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAG9B"}
|
|
@@ -1,28 +1,43 @@
|
|
|
1
1
|
import { createLogger } from '@aztec/foundation/log';
|
|
2
|
+
import { Timer } from '@aztec/foundation/timer';
|
|
2
3
|
import { createReadOnlyFileStore } from '@aztec/stdlib/file-store';
|
|
3
4
|
import { Tx } from '@aztec/stdlib/tx';
|
|
5
|
+
import { Metrics, getTelemetryClient } from '@aztec/telemetry-client';
|
|
4
6
|
/** TxSource implementation that downloads txs from a file store. */ export class FileStoreTxSource {
|
|
5
7
|
fileStore;
|
|
6
8
|
baseUrl;
|
|
9
|
+
basePath;
|
|
7
10
|
log;
|
|
8
|
-
|
|
11
|
+
downloadsSuccess;
|
|
12
|
+
downloadsFailed;
|
|
13
|
+
downloadDuration;
|
|
14
|
+
downloadSize;
|
|
15
|
+
constructor(fileStore, baseUrl, basePath, log, telemetry){
|
|
9
16
|
this.fileStore = fileStore;
|
|
10
17
|
this.baseUrl = baseUrl;
|
|
18
|
+
this.basePath = basePath;
|
|
11
19
|
this.log = log;
|
|
20
|
+
const meter = telemetry.getMeter('file-store-tx-source');
|
|
21
|
+
this.downloadsSuccess = meter.createUpDownCounter(Metrics.TX_FILE_STORE_DOWNLOADS_SUCCESS);
|
|
22
|
+
this.downloadsFailed = meter.createUpDownCounter(Metrics.TX_FILE_STORE_DOWNLOADS_FAILED);
|
|
23
|
+
this.downloadDuration = meter.createHistogram(Metrics.TX_FILE_STORE_DOWNLOAD_DURATION);
|
|
24
|
+
this.downloadSize = meter.createHistogram(Metrics.TX_FILE_STORE_DOWNLOAD_SIZE);
|
|
12
25
|
}
|
|
13
26
|
/**
|
|
14
27
|
* Creates a FileStoreTxSource from a URL.
|
|
15
28
|
* @param url - The file store URL (s3://, gs://, file://, http://, https://).
|
|
29
|
+
* @param basePath - Base path for tx files within the store.
|
|
16
30
|
* @param log - Optional logger.
|
|
31
|
+
* @param telemetry - Optional telemetry client.
|
|
17
32
|
* @returns The FileStoreTxSource instance, or undefined if creation fails.
|
|
18
|
-
*/ static async create(url, log = createLogger('p2p:file_store_tx_source')) {
|
|
33
|
+
*/ static async create(url, basePath, log = createLogger('p2p:file_store_tx_source'), telemetry = getTelemetryClient()) {
|
|
19
34
|
try {
|
|
20
35
|
const fileStore = await createReadOnlyFileStore(url, log);
|
|
21
36
|
if (!fileStore) {
|
|
22
37
|
log.warn(`Failed to create file store for URL: ${url}`);
|
|
23
38
|
return undefined;
|
|
24
39
|
}
|
|
25
|
-
return new FileStoreTxSource(fileStore, url, log);
|
|
40
|
+
return new FileStoreTxSource(fileStore, url, basePath, log, telemetry);
|
|
26
41
|
} catch (err) {
|
|
27
42
|
log.warn(`Error creating file store for URL: ${url}`, {
|
|
28
43
|
error: err
|
|
@@ -33,25 +48,43 @@ import { Tx } from '@aztec/stdlib/tx';
|
|
|
33
48
|
getInfo() {
|
|
34
49
|
return `file-store:${this.baseUrl}`;
|
|
35
50
|
}
|
|
36
|
-
getTxsByHash(txHashes) {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
51
|
+
async getTxsByHash(txHashes) {
|
|
52
|
+
const invalidTxHashes = [];
|
|
53
|
+
return {
|
|
54
|
+
validTxs: (await Promise.all(txHashes.map(async (txHash)=>{
|
|
55
|
+
const path = `${this.basePath}/txs/${txHash.toString()}.bin`;
|
|
56
|
+
const timer = new Timer();
|
|
57
|
+
try {
|
|
58
|
+
const buffer = await this.fileStore.read(path);
|
|
59
|
+
const tx = Tx.fromBuffer(buffer);
|
|
60
|
+
if (await tx.validateTxHash() && txHash.equals(tx.txHash)) {
|
|
61
|
+
this.downloadsSuccess.add(1);
|
|
62
|
+
this.downloadDuration.record(Math.ceil(timer.ms()));
|
|
63
|
+
this.downloadSize.record(buffer.length);
|
|
64
|
+
return tx;
|
|
65
|
+
} else {
|
|
66
|
+
invalidTxHashes.push(tx.txHash.toString());
|
|
67
|
+
this.downloadsFailed.add(1);
|
|
68
|
+
return undefined;
|
|
69
|
+
}
|
|
70
|
+
} catch {
|
|
71
|
+
// Tx not found or error reading - return undefined
|
|
72
|
+
this.downloadsFailed.add(1);
|
|
73
|
+
return undefined;
|
|
74
|
+
}
|
|
75
|
+
}))).filter((tx)=>tx !== undefined),
|
|
76
|
+
invalidTxHashes: invalidTxHashes
|
|
77
|
+
};
|
|
47
78
|
}
|
|
48
79
|
}
|
|
49
80
|
/**
|
|
50
81
|
* Creates FileStoreTxSource instances from URLs.
|
|
51
82
|
* @param urls - Array of file store URLs.
|
|
83
|
+
* @param basePath - Base path for tx files within each store.
|
|
52
84
|
* @param log - Optional logger.
|
|
85
|
+
* @param telemetry - Optional telemetry client.
|
|
53
86
|
* @returns Array of successfully created FileStoreTxSource instances.
|
|
54
|
-
*/ export async function createFileStoreTxSources(urls, log = createLogger('p2p:file_store_tx_source')) {
|
|
55
|
-
const sources = await Promise.all(urls.map((url)=>FileStoreTxSource.create(url, log)));
|
|
87
|
+
*/ export async function createFileStoreTxSources(urls, basePath, log = createLogger('p2p:file_store_tx_source'), telemetry = getTelemetryClient()) {
|
|
88
|
+
const sources = await Promise.all(urls.map((url)=>FileStoreTxSource.create(url, basePath, log, telemetry)));
|
|
56
89
|
return sources.filter((s)=>s !== undefined);
|
|
57
90
|
}
|
|
@@ -7,4 +7,4 @@ export declare class TxCollectionInstrumentation {
|
|
|
7
7
|
constructor(client: TelemetryClient, name: string);
|
|
8
8
|
increaseTxsFor(what: CollectionMethod, count: number, duration: number): void;
|
|
9
9
|
}
|
|
10
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
10
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5zdHJ1bWVudGF0aW9uLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvc2VydmljZXMvdHhfY29sbGVjdGlvbi9pbnN0cnVtZW50YXRpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUlMLEtBQUssZUFBZSxFQUdyQixNQUFNLHlCQUF5QixDQUFDO0FBRWpDLE9BQU8sS0FBSyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFFM0QscUJBQWEsMkJBQTJCO0lBQ3RDLE9BQU8sQ0FBQyxZQUFZLENBQWdCO0lBQ3BDLE9BQU8sQ0FBQyx1QkFBdUIsQ0FBWTtJQUMzQyxPQUFPLENBQUMsNEJBQTRCLENBQVk7SUFFaEQsWUFBWSxNQUFNLEVBQUUsZUFBZSxFQUFFLElBQUksRUFBRSxNQUFNLEVBZ0JoRDtJQUVELGNBQWMsQ0FBQyxJQUFJLEVBQUUsZ0JBQWdCLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsTUFBTSxRQUtyRTtDQUNGIn0=
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instrumentation.d.ts","sourceRoot":"","sources":["../../../src/services/tx_collection/instrumentation.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,eAAe,EAGrB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAE3D,qBAAa,2BAA2B;IACtC,OAAO,CAAC,YAAY,CAAgB;IACpC,OAAO,CAAC,uBAAuB,CAAY;IAC3C,OAAO,CAAC,4BAA4B,CAAY;IAEhD,YAAY,MAAM,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"instrumentation.d.ts","sourceRoot":"","sources":["../../../src/services/tx_collection/instrumentation.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,eAAe,EAGrB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAE3D,qBAAa,2BAA2B;IACtC,OAAO,CAAC,YAAY,CAAgB;IACpC,OAAO,CAAC,uBAAuB,CAAY;IAC3C,OAAO,CAAC,4BAA4B,CAAY;IAEhD,YAAY,MAAM,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,EAgBhD;IAED,cAAc,CAAC,IAAI,EAAE,gBAAgB,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,QAKrE;CACF"}
|
|
@@ -10,7 +10,8 @@ export class TxCollectionInstrumentation {
|
|
|
10
10
|
'fast-req-resp',
|
|
11
11
|
'fast-node-rpc',
|
|
12
12
|
'slow-req-resp',
|
|
13
|
-
'slow-node-rpc'
|
|
13
|
+
'slow-node-rpc',
|
|
14
|
+
'file-store'
|
|
14
15
|
]
|
|
15
16
|
});
|
|
16
17
|
this.collectionDurationPerTx = meter.createHistogram(Metrics.TX_COLLECTOR_DURATION_PER_TX);
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { TxHash } from '@aztec/stdlib/tx';
|
|
2
|
+
import type { Tx } from '@aztec/stdlib/tx';
|
|
3
|
+
/**
|
|
4
|
+
* Tracks which transactions are still missing and need to be fetched.
|
|
5
|
+
* Allows external code to mark transactions as fetched, enabling coordination
|
|
6
|
+
* between multiple fetching mechanisms (e.g., BatchTxRequester and Rpc Node requests).
|
|
7
|
+
*/
|
|
8
|
+
export interface IMissingTxsTracker {
|
|
9
|
+
/** Returns the set of transaction hashes that are still missing. */
|
|
10
|
+
get missingTxHashes(): Set<string>;
|
|
11
|
+
/** Size of this.missingTxHashes */
|
|
12
|
+
get numberOfMissingTxs(): number;
|
|
13
|
+
/** Are all requested txs are fetched */
|
|
14
|
+
allFetched(): boolean;
|
|
15
|
+
/** Checks that transaction is still missing */
|
|
16
|
+
isMissing(txHash: string): boolean;
|
|
17
|
+
/** Marks a transaction as fetched. Returns true if it was previously missing. */
|
|
18
|
+
markFetched(tx: Tx): boolean;
|
|
19
|
+
/** Get list of collected txs */
|
|
20
|
+
get collectedTxs(): Tx[];
|
|
21
|
+
}
|
|
22
|
+
export declare class MissingTxsTracker implements IMissingTxsTracker {
|
|
23
|
+
readonly missingTxHashes: Set<string>;
|
|
24
|
+
readonly collectedTxs: Tx[];
|
|
25
|
+
private constructor();
|
|
26
|
+
static fromArray(hashes: TxHash[] | string[]): MissingTxsTracker;
|
|
27
|
+
markFetched(tx: Tx): boolean;
|
|
28
|
+
get numberOfMissingTxs(): number;
|
|
29
|
+
allFetched(): boolean;
|
|
30
|
+
isMissing(txHash: string): boolean;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWlzc2luZ190eHNfdHJhY2tlci5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3NlcnZpY2VzL3R4X2NvbGxlY3Rpb24vbWlzc2luZ190eHNfdHJhY2tlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDMUMsT0FBTyxLQUFLLEVBQUUsRUFBRSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFFM0M7Ozs7R0FJRztBQUNILE1BQU0sV0FBVyxrQkFBa0I7SUFDakMsb0VBQW9FO0lBQ3BFLElBQUksZUFBZSxJQUFJLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUNuQyxtQ0FBbUM7SUFDbkMsSUFBSSxrQkFBa0IsSUFBSSxNQUFNLENBQUM7SUFDakMsd0NBQXdDO0lBQ3hDLFVBQVUsSUFBSSxPQUFPLENBQUM7SUFDdEIsK0NBQStDO0lBQy9DLFNBQVMsQ0FBQyxNQUFNLEVBQUUsTUFBTSxHQUFHLE9BQU8sQ0FBQztJQUNuQyxpRkFBaUY7SUFDakYsV0FBVyxDQUFDLEVBQUUsRUFBRSxFQUFFLEdBQUcsT0FBTyxDQUFDO0lBQzdCLGdDQUFnQztJQUNoQyxJQUFJLFlBQVksSUFBSSxFQUFFLEVBQUUsQ0FBQztDQUMxQjtBQUVELHFCQUFhLGlCQUFrQixZQUFXLGtCQUFrQjthQUd0QixlQUFlLEVBQUUsR0FBRyxDQUFDLE1BQU0sQ0FBQztJQUZoRSxTQUFnQixZQUFZLEVBQUUsRUFBRSxFQUFFLENBQU07SUFFeEMsT0FBTyxlQUE2RDtJQUVwRSxPQUFjLFNBQVMsQ0FBQyxNQUFNLEVBQUUsTUFBTSxFQUFFLEdBQUcsTUFBTSxFQUFFLHFCQUVsRDtJQUVELFdBQVcsQ0FBQyxFQUFFLEVBQUUsRUFBRSxHQUFHLE9BQU8sQ0FNM0I7SUFFRCxJQUFJLGtCQUFrQixJQUFJLE1BQU0sQ0FFL0I7SUFFRCxVQUFVLElBQUksT0FBTyxDQUVwQjtJQUVELFNBQVMsQ0FBQyxNQUFNLEVBQUUsTUFBTSxHQUFHLE9BQU8sQ0FFakM7Q0FDRiJ9
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"missing_txs_tracker.d.ts","sourceRoot":"","sources":["../../../src/services/tx_collection/missing_txs_tracker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AAE3C;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,oEAAoE;IACpE,IAAI,eAAe,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;IACnC,mCAAmC;IACnC,IAAI,kBAAkB,IAAI,MAAM,CAAC;IACjC,wCAAwC;IACxC,UAAU,IAAI,OAAO,CAAC;IACtB,+CAA+C;IAC/C,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;IACnC,iFAAiF;IACjF,WAAW,CAAC,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC;IAC7B,gCAAgC;IAChC,IAAI,YAAY,IAAI,EAAE,EAAE,CAAC;CAC1B;AAED,qBAAa,iBAAkB,YAAW,kBAAkB;aAGtB,eAAe,EAAE,GAAG,CAAC,MAAM,CAAC;IAFhE,SAAgB,YAAY,EAAE,EAAE,EAAE,CAAM;IAExC,OAAO,eAA6D;IAEpE,OAAc,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,qBAElD;IAED,WAAW,CAAC,EAAE,EAAE,EAAE,GAAG,OAAO,CAM3B;IAED,IAAI,kBAAkB,IAAI,MAAM,CAE/B;IAED,UAAU,IAAI,OAAO,CAEpB;IAED,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEjC;CACF"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export class MissingTxsTracker {
|
|
2
|
+
missingTxHashes;
|
|
3
|
+
collectedTxs;
|
|
4
|
+
constructor(missingTxHashes){
|
|
5
|
+
this.missingTxHashes = missingTxHashes;
|
|
6
|
+
this.collectedTxs = [];
|
|
7
|
+
}
|
|
8
|
+
static fromArray(hashes) {
|
|
9
|
+
return new MissingTxsTracker(new Set(hashes.map((hash)=>hash.toString())));
|
|
10
|
+
}
|
|
11
|
+
markFetched(tx) {
|
|
12
|
+
if (this.missingTxHashes.delete(tx.txHash.toString())) {
|
|
13
|
+
this.collectedTxs.push(tx);
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
get numberOfMissingTxs() {
|
|
19
|
+
return this.missingTxHashes.size;
|
|
20
|
+
}
|
|
21
|
+
allFetched() {
|
|
22
|
+
return this.numberOfMissingTxs === 0;
|
|
23
|
+
}
|
|
24
|
+
isMissing(txHash) {
|
|
25
|
+
return this.missingTxHashes.has(txHash.toString());
|
|
26
|
+
}
|
|
27
|
+
}
|