@aztec/p2p 0.0.0-test.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/README.md +7 -0
- package/dest/bootstrap/bootstrap.d.ts +38 -0
- package/dest/bootstrap/bootstrap.d.ts.map +1 -0
- package/dest/bootstrap/bootstrap.js +123 -0
- package/dest/client/factory.d.ts +21 -0
- package/dest/client/factory.d.ts.map +1 -0
- package/dest/client/factory.js +37 -0
- package/dest/client/index.d.ts +3 -0
- package/dest/client/index.d.ts.map +1 -0
- package/dest/client/index.js +2 -0
- package/dest/client/p2p_client.d.ts +314 -0
- package/dest/client/p2p_client.d.ts.map +1 -0
- package/dest/client/p2p_client.js +505 -0
- package/dest/config.d.ts +180 -0
- package/dest/config.d.ts.map +1 -0
- package/dest/config.js +193 -0
- package/dest/enr/generate-enr.d.ts +9 -0
- package/dest/enr/generate-enr.d.ts.map +1 -0
- package/dest/enr/generate-enr.js +30 -0
- package/dest/enr/index.d.ts +2 -0
- package/dest/enr/index.d.ts.map +1 -0
- package/dest/enr/index.js +1 -0
- package/dest/errors/reqresp.error.d.ts +28 -0
- package/dest/errors/reqresp.error.d.ts.map +1 -0
- package/dest/errors/reqresp.error.js +30 -0
- package/dest/index.d.ts +8 -0
- package/dest/index.d.ts.map +1 -0
- package/dest/index.js +7 -0
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +57 -0
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -0
- package/dest/mem_pools/attestation_pool/attestation_pool.js +6 -0
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts +3 -0
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts.map +1 -0
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.js +195 -0
- package/dest/mem_pools/attestation_pool/index.d.ts +3 -0
- package/dest/mem_pools/attestation_pool/index.d.ts.map +1 -0
- package/dest/mem_pools/attestation_pool/index.js +2 -0
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts +22 -0
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts.map +1 -0
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.js +112 -0
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts +17 -0
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts.map +1 -0
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.js +129 -0
- package/dest/mem_pools/attestation_pool/mocks.d.ts +19 -0
- package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -0
- package/dest/mem_pools/attestation_pool/mocks.js +33 -0
- package/dest/mem_pools/index.d.ts +4 -0
- package/dest/mem_pools/index.d.ts.map +1 -0
- package/dest/mem_pools/index.js +1 -0
- package/dest/mem_pools/instrumentation.d.ts +30 -0
- package/dest/mem_pools/instrumentation.d.ts.map +1 -0
- package/dest/mem_pools/instrumentation.js +84 -0
- package/dest/mem_pools/interface.d.ts +11 -0
- package/dest/mem_pools/interface.d.ts.map +1 -0
- package/dest/mem_pools/interface.js +3 -0
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts +66 -0
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.js +245 -0
- package/dest/mem_pools/tx_pool/index.d.ts +4 -0
- package/dest/mem_pools/tx_pool/index.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/index.js +3 -0
- package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts +56 -0
- package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/memory_tx_pool.js +141 -0
- package/dest/mem_pools/tx_pool/priority.d.ts +8 -0
- package/dest/mem_pools/tx_pool/priority.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/priority.js +10 -0
- package/dest/mem_pools/tx_pool/tx_pool.d.ts +66 -0
- package/dest/mem_pools/tx_pool/tx_pool.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/tx_pool.js +3 -0
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts +7 -0
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.js +169 -0
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +8 -0
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -0
- package/dest/msg_validators/attestation_validator/attestation_validator.js +19 -0
- package/dest/msg_validators/attestation_validator/index.d.ts +2 -0
- package/dest/msg_validators/attestation_validator/index.d.ts.map +1 -0
- package/dest/msg_validators/attestation_validator/index.js +1 -0
- package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts +8 -0
- package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts.map +1 -0
- package/dest/msg_validators/block_proposal_validator/block_proposal_validator.js +21 -0
- package/dest/msg_validators/block_proposal_validator/index.d.ts +2 -0
- package/dest/msg_validators/block_proposal_validator/index.d.ts.map +1 -0
- package/dest/msg_validators/block_proposal_validator/index.js +1 -0
- package/dest/msg_validators/index.d.ts +4 -0
- package/dest/msg_validators/index.d.ts.map +1 -0
- package/dest/msg_validators/index.js +3 -0
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts +7 -0
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.js +31 -0
- package/dest/msg_validators/tx_validator/block_header_validator.d.ts +11 -0
- package/dest/msg_validators/tx_validator/block_header_validator.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/block_header_validator.js +26 -0
- package/dest/msg_validators/tx_validator/data_validator.d.ts +6 -0
- package/dest/msg_validators/tx_validator/data_validator.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/data_validator.js +107 -0
- package/dest/msg_validators/tx_validator/double_spend_validator.d.ts +12 -0
- package/dest/msg_validators/tx_validator/double_spend_validator.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/double_spend_validator.js +41 -0
- package/dest/msg_validators/tx_validator/index.d.ts +7 -0
- package/dest/msg_validators/tx_validator/index.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/index.js +6 -0
- package/dest/msg_validators/tx_validator/metadata_validator.d.ts +10 -0
- package/dest/msg_validators/tx_validator/metadata_validator.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/metadata_validator.js +44 -0
- package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts +9 -0
- package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/tx_proof_validator.js +25 -0
- package/dest/services/data_store.d.ts +27 -0
- package/dest/services/data_store.d.ts.map +1 -0
- package/dest/services/data_store.js +188 -0
- package/dest/services/discv5/discV5_service.d.ts +42 -0
- package/dest/services/discv5/discV5_service.d.ts.map +1 -0
- package/dest/services/discv5/discV5_service.js +214 -0
- package/dest/services/dummy_service.d.ts +85 -0
- package/dest/services/dummy_service.d.ts.map +1 -0
- package/dest/services/dummy_service.js +92 -0
- package/dest/services/encoding.d.ts +31 -0
- package/dest/services/encoding.d.ts.map +1 -0
- package/dest/services/encoding.js +66 -0
- package/dest/services/gossipsub/scoring.d.ts +7 -0
- package/dest/services/gossipsub/scoring.d.ts.map +1 -0
- package/dest/services/gossipsub/scoring.js +10 -0
- package/dest/services/index.d.ts +3 -0
- package/dest/services/index.d.ts.map +1 -0
- package/dest/services/index.js +2 -0
- package/dest/services/libp2p/libp2p_service.d.ts +186 -0
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -0
- package/dest/services/libp2p/libp2p_service.js +712 -0
- package/dest/services/peer-manager/metrics.d.ts +12 -0
- package/dest/services/peer-manager/metrics.d.ts.map +1 -0
- package/dest/services/peer-manager/metrics.js +33 -0
- package/dest/services/peer-manager/peer_manager.d.ts +94 -0
- package/dest/services/peer-manager/peer_manager.d.ts.map +1 -0
- package/dest/services/peer-manager/peer_manager.js +445 -0
- package/dest/services/peer-manager/peer_scoring.d.ts +28 -0
- package/dest/services/peer-manager/peer_scoring.d.ts.map +1 -0
- package/dest/services/peer-manager/peer_scoring.js +86 -0
- package/dest/services/reqresp/config.d.ts +16 -0
- package/dest/services/reqresp/config.d.ts.map +1 -0
- package/dest/services/reqresp/config.js +20 -0
- package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts +45 -0
- package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts.map +1 -0
- package/dest/services/reqresp/connection-sampler/batch_connection_sampler.js +88 -0
- package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts +61 -0
- package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts.map +1 -0
- package/dest/services/reqresp/connection-sampler/connection_sampler.js +181 -0
- package/dest/services/reqresp/index.d.ts +6 -0
- package/dest/services/reqresp/index.d.ts.map +1 -0
- package/dest/services/reqresp/index.js +4 -0
- package/dest/services/reqresp/interface.d.ts +116 -0
- package/dest/services/reqresp/interface.d.ts.map +1 -0
- package/dest/services/reqresp/interface.js +84 -0
- package/dest/services/reqresp/metrics.d.ts +15 -0
- package/dest/services/reqresp/metrics.d.ts.map +1 -0
- package/dest/services/reqresp/metrics.js +55 -0
- package/dest/services/reqresp/protocols/block.d.ts +4 -0
- package/dest/services/reqresp/protocols/block.d.ts.map +1 -0
- package/dest/services/reqresp/protocols/block.js +8 -0
- package/dest/services/reqresp/protocols/goodbye.d.ts +51 -0
- package/dest/services/reqresp/protocols/goodbye.d.ts.map +1 -0
- package/dest/services/reqresp/protocols/goodbye.js +87 -0
- package/dest/services/reqresp/protocols/index.d.ts +9 -0
- package/dest/services/reqresp/protocols/index.d.ts.map +1 -0
- package/dest/services/reqresp/protocols/index.js +7 -0
- package/dest/services/reqresp/protocols/ping.d.ts +9 -0
- package/dest/services/reqresp/protocols/ping.d.ts.map +1 -0
- package/dest/services/reqresp/protocols/ping.js +7 -0
- package/dest/services/reqresp/protocols/status.d.ts +9 -0
- package/dest/services/reqresp/protocols/status.d.ts.map +1 -0
- package/dest/services/reqresp/protocols/status.js +7 -0
- package/dest/services/reqresp/protocols/tx.d.ts +13 -0
- package/dest/services/reqresp/protocols/tx.d.ts.map +1 -0
- package/dest/services/reqresp/protocols/tx.js +20 -0
- package/dest/services/reqresp/rate-limiter/index.d.ts +2 -0
- package/dest/services/reqresp/rate-limiter/index.d.ts.map +1 -0
- package/dest/services/reqresp/rate-limiter/index.js +1 -0
- package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts +102 -0
- package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts.map +1 -0
- package/dest/services/reqresp/rate-limiter/rate_limiter.js +184 -0
- package/dest/services/reqresp/rate-limiter/rate_limits.d.ts +3 -0
- package/dest/services/reqresp/rate-limiter/rate_limits.d.ts.map +1 -0
- package/dest/services/reqresp/rate-limiter/rate_limits.js +54 -0
- package/dest/services/reqresp/reqresp.d.ts +166 -0
- package/dest/services/reqresp/reqresp.d.ts.map +1 -0
- package/dest/services/reqresp/reqresp.js +516 -0
- package/dest/services/reqresp/status.d.ts +31 -0
- package/dest/services/reqresp/status.d.ts.map +1 -0
- package/dest/services/reqresp/status.js +51 -0
- package/dest/services/service.d.ts +87 -0
- package/dest/services/service.d.ts.map +1 -0
- package/dest/services/service.js +5 -0
- package/dest/test-helpers/generate-peer-id-private-keys.d.ts +7 -0
- package/dest/test-helpers/generate-peer-id-private-keys.d.ts.map +1 -0
- package/dest/test-helpers/generate-peer-id-private-keys.js +13 -0
- package/dest/test-helpers/get-ports.d.ts +7 -0
- package/dest/test-helpers/get-ports.d.ts.map +1 -0
- package/dest/test-helpers/get-ports.js +8 -0
- package/dest/test-helpers/index.d.ts +6 -0
- package/dest/test-helpers/index.d.ts.map +1 -0
- package/dest/test-helpers/index.js +5 -0
- package/dest/test-helpers/make-enrs.d.ts +16 -0
- package/dest/test-helpers/make-enrs.d.ts.map +1 -0
- package/dest/test-helpers/make-enrs.js +32 -0
- package/dest/test-helpers/make-test-p2p-clients.d.ts +36 -0
- package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -0
- package/dest/test-helpers/make-test-p2p-clients.js +68 -0
- package/dest/test-helpers/reqresp-nodes.d.ts +66 -0
- package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -0
- package/dest/test-helpers/reqresp-nodes.js +207 -0
- package/dest/testbench/p2p_client_testbench_worker.d.ts +2 -0
- package/dest/testbench/p2p_client_testbench_worker.d.ts.map +1 -0
- package/dest/testbench/p2p_client_testbench_worker.js +132 -0
- package/dest/testbench/parse_log_file.d.ts +2 -0
- package/dest/testbench/parse_log_file.d.ts.map +1 -0
- package/dest/testbench/parse_log_file.js +131 -0
- package/dest/testbench/testbench.d.ts +2 -0
- package/dest/testbench/testbench.d.ts.map +1 -0
- package/dest/testbench/testbench.js +61 -0
- package/dest/testbench/worker_client_manager.d.ts +56 -0
- package/dest/testbench/worker_client_manager.d.ts.map +1 -0
- package/dest/testbench/worker_client_manager.js +266 -0
- package/dest/types/index.d.ts +32 -0
- package/dest/types/index.d.ts.map +1 -0
- package/dest/types/index.js +28 -0
- package/dest/util.d.ts +53 -0
- package/dest/util.d.ts.map +1 -0
- package/dest/util.js +140 -0
- package/dest/versioning.d.ts +12 -0
- package/dest/versioning.d.ts.map +1 -0
- package/dest/versioning.js +33 -0
- package/package.json +127 -0
- package/src/bootstrap/bootstrap.ts +146 -0
- package/src/client/factory.ts +89 -0
- package/src/client/index.ts +2 -0
- package/src/client/p2p_client.ts +754 -0
- package/src/config.ts +371 -0
- package/src/enr/generate-enr.ts +39 -0
- package/src/enr/index.ts +1 -0
- package/src/errors/reqresp.error.ts +35 -0
- package/src/index.ts +7 -0
- package/src/mem_pools/attestation_pool/attestation_pool.ts +62 -0
- package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +230 -0
- package/src/mem_pools/attestation_pool/index.ts +2 -0
- package/src/mem_pools/attestation_pool/kv_attestation_pool.ts +159 -0
- package/src/mem_pools/attestation_pool/memory_attestation_pool.ts +161 -0
- package/src/mem_pools/attestation_pool/mocks.ts +44 -0
- package/src/mem_pools/index.ts +3 -0
- package/src/mem_pools/instrumentation.ts +126 -0
- package/src/mem_pools/interface.ts +12 -0
- package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +309 -0
- package/src/mem_pools/tx_pool/index.ts +3 -0
- package/src/mem_pools/tx_pool/memory_tx_pool.ts +174 -0
- package/src/mem_pools/tx_pool/priority.ts +13 -0
- package/src/mem_pools/tx_pool/tx_pool.ts +76 -0
- package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +130 -0
- package/src/msg_validators/attestation_validator/attestation_validator.ts +26 -0
- package/src/msg_validators/attestation_validator/index.ts +1 -0
- package/src/msg_validators/block_proposal_validator/block_proposal_validator.ts +29 -0
- package/src/msg_validators/block_proposal_validator/index.ts +1 -0
- package/src/msg_validators/index.ts +3 -0
- package/src/msg_validators/tx_validator/aggregate_tx_validator.ts +32 -0
- package/src/msg_validators/tx_validator/block_header_validator.ts +25 -0
- package/src/msg_validators/tx_validator/data_validator.ts +106 -0
- package/src/msg_validators/tx_validator/double_spend_validator.ts +38 -0
- package/src/msg_validators/tx_validator/index.ts +6 -0
- package/src/msg_validators/tx_validator/metadata_validator.ts +48 -0
- package/src/msg_validators/tx_validator/tx_proof_validator.ts +18 -0
- package/src/services/data_store.ts +235 -0
- package/src/services/discv5/discV5_service.ts +256 -0
- package/src/services/dummy_service.ts +134 -0
- package/src/services/encoding.ts +79 -0
- package/src/services/gossipsub/scoring.ts +13 -0
- package/src/services/index.ts +2 -0
- package/src/services/libp2p/libp2p_service.ts +871 -0
- package/src/services/peer-manager/metrics.ts +41 -0
- package/src/services/peer-manager/peer_manager.ts +530 -0
- package/src/services/peer-manager/peer_scoring.ts +105 -0
- package/src/services/reqresp/config.ts +35 -0
- package/src/services/reqresp/connection-sampler/batch_connection_sampler.ts +94 -0
- package/src/services/reqresp/connection-sampler/connection_sampler.ts +217 -0
- package/src/services/reqresp/index.ts +4 -0
- package/src/services/reqresp/interface.ts +185 -0
- package/src/services/reqresp/metrics.ts +57 -0
- package/src/services/reqresp/protocols/block.ts +15 -0
- package/src/services/reqresp/protocols/goodbye.ts +101 -0
- package/src/services/reqresp/protocols/index.ts +8 -0
- package/src/services/reqresp/protocols/ping.ts +8 -0
- package/src/services/reqresp/protocols/status.ts +8 -0
- package/src/services/reqresp/protocols/tx.ts +29 -0
- package/src/services/reqresp/rate-limiter/index.ts +1 -0
- package/src/services/reqresp/rate-limiter/rate_limiter.ts +228 -0
- package/src/services/reqresp/rate-limiter/rate_limits.ts +55 -0
- package/src/services/reqresp/reqresp.ts +661 -0
- package/src/services/reqresp/status.ts +59 -0
- package/src/services/service.ts +112 -0
- package/src/test-helpers/generate-peer-id-private-keys.ts +15 -0
- package/src/test-helpers/get-ports.ts +8 -0
- package/src/test-helpers/index.ts +5 -0
- package/src/test-helpers/make-enrs.ts +44 -0
- package/src/test-helpers/make-test-p2p-clients.ts +122 -0
- package/src/test-helpers/reqresp-nodes.ts +289 -0
- package/src/testbench/README.md +20 -0
- package/src/testbench/p2p_client_testbench_worker.ts +152 -0
- package/src/testbench/parse_log_file.ts +175 -0
- package/src/testbench/testbench.ts +66 -0
- package/src/testbench/worker_client_manager.ts +318 -0
- package/src/types/index.ts +36 -0
- package/src/util.ts +196 -0
- package/src/versioning.ts +50 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import type { Tx, TxHash } from '@aztec/stdlib/tx';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Interface of a transaction pool. The pool includes tx requests and is kept up-to-date by a P2P client.
|
|
5
|
+
*/
|
|
6
|
+
export interface TxPool {
|
|
7
|
+
/**
|
|
8
|
+
* Adds a list of transactions to the pool. Duplicates are ignored.
|
|
9
|
+
* @param txs - An array of txs to be added to the pool.
|
|
10
|
+
*/
|
|
11
|
+
addTxs(txs: Tx[]): Promise<void>;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Checks if a transaction exists in the pool and returns it.
|
|
15
|
+
* @param txHash - The hash of the transaction, used as an ID.
|
|
16
|
+
* @returns The transaction, if found, 'undefined' otherwise.
|
|
17
|
+
*/
|
|
18
|
+
getTxByHash(txHash: TxHash): Promise<Tx | undefined>;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Checks if an archived transaction exists in the pool and returns it.
|
|
22
|
+
* @param txHash - The hash of the transaction, used as an ID.
|
|
23
|
+
* @returns The transaction, if found, 'undefined' otherwise.
|
|
24
|
+
*/
|
|
25
|
+
getArchivedTxByHash(txHash: TxHash): Promise<Tx | undefined>;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Marks the set of txs as mined, as opposed to pending.
|
|
29
|
+
* @param txHashes - Hashes of the txs to flag as mined.
|
|
30
|
+
*/
|
|
31
|
+
markAsMined(txHashes: TxHash[], blockNumber: number): Promise<void>;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Moves mined txs back to the pending set in the case of a reorg.
|
|
35
|
+
* Note: txs not known by this peer will be ignored.
|
|
36
|
+
* @param txHashes - Hashes of the txs to flag as pending.
|
|
37
|
+
*/
|
|
38
|
+
markMinedAsPending(txHashes: TxHash[]): Promise<void>;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Deletes transactions from the pool. Tx hashes that are not present are ignored.
|
|
42
|
+
* @param txHashes - An array of tx hashes to be removed from the tx pool.
|
|
43
|
+
*/
|
|
44
|
+
deleteTxs(txHashes: TxHash[]): Promise<void>;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Gets all transactions currently in the tx pool.
|
|
48
|
+
* @returns An array of transaction objects found in the tx pool.
|
|
49
|
+
*/
|
|
50
|
+
getAllTxs(): Promise<Tx[]>;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Gets the hashes of all transactions currently in the tx pool.
|
|
54
|
+
* @returns An array of transaction hashes found in the tx pool.
|
|
55
|
+
*/
|
|
56
|
+
getAllTxHashes(): Promise<TxHash[]>;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Gets the hashes of pending transactions currently in the tx pool sorted by priority (see getPendingTxPriority).
|
|
60
|
+
* @returns An array of pending transaction hashes found in the tx pool.
|
|
61
|
+
*/
|
|
62
|
+
getPendingTxHashes(): Promise<TxHash[]>;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Gets the hashes of mined transactions currently in the tx pool.
|
|
66
|
+
* @returns An array of mined transaction hashes found in the tx pool.
|
|
67
|
+
*/
|
|
68
|
+
getMinedTxHashes(): Promise<[tx: TxHash, blockNumber: number][]>;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Returns whether the given tx hash is flagged as pending or mined.
|
|
72
|
+
* @param txHash - Hash of the tx to query.
|
|
73
|
+
* @returns Pending or mined depending on its status, or undefined if not found.
|
|
74
|
+
*/
|
|
75
|
+
getTxStatus(txHash: TxHash): Promise<'pending' | 'mined' | undefined>;
|
|
76
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { unfreeze } from '@aztec/foundation/types';
|
|
2
|
+
import { GasFees } from '@aztec/stdlib/gas';
|
|
3
|
+
import { mockTx } from '@aztec/stdlib/testing';
|
|
4
|
+
import type { Tx } from '@aztec/stdlib/tx';
|
|
5
|
+
|
|
6
|
+
import type { TxPool } from './tx_pool.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Tests a TxPool implementation.
|
|
10
|
+
* @param getTxPool - Gets a fresh TxPool
|
|
11
|
+
*/
|
|
12
|
+
export function describeTxPool(getTxPool: () => TxPool) {
|
|
13
|
+
let pool: TxPool;
|
|
14
|
+
|
|
15
|
+
beforeEach(() => {
|
|
16
|
+
pool = getTxPool();
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it('Adds txs to the pool as pending', async () => {
|
|
20
|
+
const tx1 = await mockTx();
|
|
21
|
+
|
|
22
|
+
await pool.addTxs([tx1]);
|
|
23
|
+
const poolTx = await pool.getTxByHash(await tx1.getTxHash());
|
|
24
|
+
expect(await poolTx!.getTxHash()).toEqual(await tx1.getTxHash());
|
|
25
|
+
await expect(pool.getTxStatus(await tx1.getTxHash())).resolves.toEqual('pending');
|
|
26
|
+
await expect(pool.getPendingTxHashes()).resolves.toEqual([await tx1.getTxHash()]);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('Removes txs from the pool', async () => {
|
|
30
|
+
const tx1 = await mockTx();
|
|
31
|
+
|
|
32
|
+
await pool.addTxs([tx1]);
|
|
33
|
+
await pool.deleteTxs([await tx1.getTxHash()]);
|
|
34
|
+
|
|
35
|
+
await expect(pool.getTxByHash(await tx1.getTxHash())).resolves.toBeFalsy();
|
|
36
|
+
await expect(pool.getTxStatus(await tx1.getTxHash())).resolves.toBeUndefined();
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('Marks txs as mined', async () => {
|
|
40
|
+
const tx1 = await mockTx(1);
|
|
41
|
+
const tx2 = await mockTx(2);
|
|
42
|
+
|
|
43
|
+
await pool.addTxs([tx1, tx2]);
|
|
44
|
+
await pool.markAsMined([await tx1.getTxHash()], 1);
|
|
45
|
+
|
|
46
|
+
await expect(pool.getTxByHash(await tx1.getTxHash())).resolves.toEqual(tx1);
|
|
47
|
+
await expect(pool.getTxStatus(await tx1.getTxHash())).resolves.toEqual('mined');
|
|
48
|
+
await expect(pool.getMinedTxHashes()).resolves.toEqual([[await tx1.getTxHash(), 1]]);
|
|
49
|
+
await expect(pool.getPendingTxHashes()).resolves.toEqual([await tx2.getTxHash()]);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('Marks txs as pending after being mined', async () => {
|
|
53
|
+
const tx1 = await mockTx(1);
|
|
54
|
+
const tx2 = await mockTx(2);
|
|
55
|
+
|
|
56
|
+
await pool.addTxs([tx1, tx2]);
|
|
57
|
+
await pool.markAsMined([await tx1.getTxHash()], 1);
|
|
58
|
+
|
|
59
|
+
await pool.markMinedAsPending([await tx1.getTxHash()]);
|
|
60
|
+
await expect(pool.getMinedTxHashes()).resolves.toEqual([]);
|
|
61
|
+
const pending = await pool.getPendingTxHashes();
|
|
62
|
+
expect(pending).toHaveLength(2);
|
|
63
|
+
expect(pending).toEqual(expect.arrayContaining([await tx1.getTxHash(), await tx2.getTxHash()]));
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('Only marks txs as pending if they are known', async () => {
|
|
67
|
+
const tx1 = await mockTx(1);
|
|
68
|
+
// simulate a situation where not all peers have all the txs
|
|
69
|
+
const tx2 = await mockTx(2);
|
|
70
|
+
const someTxHashThatThisPeerDidNotSee = await tx2.getTxHash();
|
|
71
|
+
await pool.addTxs([tx1]);
|
|
72
|
+
// this peer knows that tx2 was mined, but it does not have the tx object
|
|
73
|
+
await pool.markAsMined([await tx1.getTxHash(), someTxHashThatThisPeerDidNotSee], 1);
|
|
74
|
+
expect(await pool.getMinedTxHashes()).toEqual(
|
|
75
|
+
expect.arrayContaining([
|
|
76
|
+
[await tx1.getTxHash(), 1],
|
|
77
|
+
[someTxHashThatThisPeerDidNotSee, 1],
|
|
78
|
+
]),
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
// reorg: both txs should now become available again
|
|
82
|
+
await pool.markMinedAsPending([await tx1.getTxHash(), someTxHashThatThisPeerDidNotSee]);
|
|
83
|
+
await expect(pool.getMinedTxHashes()).resolves.toEqual([]);
|
|
84
|
+
await expect(pool.getPendingTxHashes()).resolves.toEqual([await tx1.getTxHash()]); // tx2 is not in the pool
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('Returns all transactions in the pool', async () => {
|
|
88
|
+
const tx1 = await mockTx(1);
|
|
89
|
+
const tx2 = await mockTx(2);
|
|
90
|
+
const tx3 = await mockTx(3);
|
|
91
|
+
|
|
92
|
+
await pool.addTxs([tx1, tx2, tx3]);
|
|
93
|
+
|
|
94
|
+
const poolTxs = await pool.getAllTxs();
|
|
95
|
+
expect(poolTxs).toHaveLength(3);
|
|
96
|
+
expect(poolTxs).toEqual(expect.arrayContaining([tx1, tx2, tx3]));
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it('Returns all txHashes in the pool', async () => {
|
|
100
|
+
const tx1 = await mockTx(1);
|
|
101
|
+
const tx2 = await mockTx(2);
|
|
102
|
+
const tx3 = await mockTx(3);
|
|
103
|
+
|
|
104
|
+
await pool.addTxs([tx1, tx2, tx3]);
|
|
105
|
+
|
|
106
|
+
const poolTxHashes = await pool.getAllTxHashes();
|
|
107
|
+
expect(poolTxHashes).toHaveLength(3);
|
|
108
|
+
expect(poolTxHashes).toEqual(
|
|
109
|
+
expect.arrayContaining([await tx1.getTxHash(), await tx2.getTxHash(), await tx3.getTxHash()]),
|
|
110
|
+
);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it('Returns pending tx hashes sorted by priority', async () => {
|
|
114
|
+
const withPriorityFee = (tx: Tx, fee: number) => {
|
|
115
|
+
unfreeze(tx.data.constants.txContext.gasSettings).maxPriorityFeesPerGas = new GasFees(fee, fee);
|
|
116
|
+
return tx;
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
const tx1 = withPriorityFee(await mockTx(0), 1000);
|
|
120
|
+
const tx2 = withPriorityFee(await mockTx(1), 100);
|
|
121
|
+
const tx3 = withPriorityFee(await mockTx(2), 200);
|
|
122
|
+
const tx4 = withPriorityFee(await mockTx(3), 3000);
|
|
123
|
+
|
|
124
|
+
await pool.addTxs([tx1, tx2, tx3, tx4]);
|
|
125
|
+
|
|
126
|
+
const poolTxHashes = await pool.getPendingTxHashes();
|
|
127
|
+
expect(poolTxHashes).toHaveLength(4);
|
|
128
|
+
expect(poolTxHashes).toEqual(await Promise.all([tx4, tx1, tx3, tx2].map(tx => tx.getTxHash())));
|
|
129
|
+
});
|
|
130
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { EpochCacheInterface } from '@aztec/epoch-cache';
|
|
2
|
+
import { type BlockAttestation, type P2PValidator, PeerErrorSeverity } from '@aztec/stdlib/p2p';
|
|
3
|
+
|
|
4
|
+
export class AttestationValidator implements P2PValidator<BlockAttestation> {
|
|
5
|
+
private epochCache: EpochCacheInterface;
|
|
6
|
+
|
|
7
|
+
constructor(epochCache: EpochCacheInterface) {
|
|
8
|
+
this.epochCache = epochCache;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
async validate(message: BlockAttestation): Promise<PeerErrorSeverity | undefined> {
|
|
12
|
+
const { currentSlot, nextSlot } = await this.epochCache.getProposerInCurrentOrNextSlot();
|
|
13
|
+
|
|
14
|
+
const slotNumberBigInt = message.payload.header.globalVariables.slotNumber.toBigInt();
|
|
15
|
+
if (slotNumberBigInt !== currentSlot && slotNumberBigInt !== nextSlot) {
|
|
16
|
+
return PeerErrorSeverity.HighToleranceError;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const attester = await message.getSender();
|
|
20
|
+
if (!(await this.epochCache.isInCommittee(attester))) {
|
|
21
|
+
return PeerErrorSeverity.HighToleranceError;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './attestation_validator.js';
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { EpochCacheInterface } from '@aztec/epoch-cache';
|
|
2
|
+
import { type BlockProposal, type P2PValidator, PeerErrorSeverity } from '@aztec/stdlib/p2p';
|
|
3
|
+
|
|
4
|
+
export class BlockProposalValidator implements P2PValidator<BlockProposal> {
|
|
5
|
+
private epochCache: EpochCacheInterface;
|
|
6
|
+
|
|
7
|
+
constructor(epochCache: EpochCacheInterface) {
|
|
8
|
+
this.epochCache = epochCache;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
async validate(block: BlockProposal): Promise<PeerErrorSeverity | undefined> {
|
|
12
|
+
const { currentProposer, nextProposer, currentSlot, nextSlot } =
|
|
13
|
+
await this.epochCache.getProposerInCurrentOrNextSlot();
|
|
14
|
+
|
|
15
|
+
// Check that the attestation is for the current or next slot
|
|
16
|
+
const slotNumberBigInt = block.payload.header.globalVariables.slotNumber.toBigInt();
|
|
17
|
+
if (slotNumberBigInt !== currentSlot && slotNumberBigInt !== nextSlot) {
|
|
18
|
+
return PeerErrorSeverity.HighToleranceError;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Check that the block proposal is from the current or next proposer
|
|
22
|
+
const proposer = await block.getSender();
|
|
23
|
+
if (!proposer.equals(currentProposer) && !proposer.equals(nextProposer)) {
|
|
24
|
+
return PeerErrorSeverity.HighToleranceError;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return undefined;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './block_proposal_validator.js';
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { ProcessedTx, Tx, TxValidationResult, TxValidator } from '@aztec/stdlib/tx';
|
|
2
|
+
|
|
3
|
+
export class AggregateTxValidator<T extends Tx | ProcessedTx> implements TxValidator<T> {
|
|
4
|
+
#validators: TxValidator<T>[];
|
|
5
|
+
constructor(...validators: TxValidator<T>[]) {
|
|
6
|
+
if (validators.length === 0) {
|
|
7
|
+
throw new Error('At least one validator must be provided');
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
this.#validators = validators;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
async validateTx(tx: T): Promise<TxValidationResult> {
|
|
14
|
+
const aggregate: { result: string; reason?: string[] } = { result: 'valid', reason: [] };
|
|
15
|
+
for (const validator of this.#validators) {
|
|
16
|
+
const result = await validator.validateTx(tx);
|
|
17
|
+
if (result.result === 'invalid') {
|
|
18
|
+
aggregate.result = 'invalid';
|
|
19
|
+
aggregate.reason!.push(...result.reason);
|
|
20
|
+
} else if (result.result === 'skipped') {
|
|
21
|
+
if (aggregate.result === 'valid') {
|
|
22
|
+
aggregate.result = 'skipped';
|
|
23
|
+
}
|
|
24
|
+
aggregate.reason!.push(...result.reason);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
if (aggregate.result === 'valid') {
|
|
28
|
+
delete aggregate.reason;
|
|
29
|
+
}
|
|
30
|
+
return aggregate as TxValidationResult;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Fr } from '@aztec/foundation/fields';
|
|
2
|
+
import { createLogger } from '@aztec/foundation/log';
|
|
3
|
+
import { type AnyTx, Tx, type TxValidationResult, type TxValidator } from '@aztec/stdlib/tx';
|
|
4
|
+
|
|
5
|
+
export interface ArchiveSource {
|
|
6
|
+
getArchiveIndices: (archives: Fr[]) => Promise<(bigint | undefined)[]>;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export class BlockHeaderTxValidator<T extends AnyTx> implements TxValidator<T> {
|
|
10
|
+
#log = createLogger('p2p:tx_validator:tx_block_header');
|
|
11
|
+
#archiveSource: ArchiveSource;
|
|
12
|
+
|
|
13
|
+
constructor(archiveSource: ArchiveSource) {
|
|
14
|
+
this.#archiveSource = archiveSource;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async validateTx(tx: T): Promise<TxValidationResult> {
|
|
18
|
+
const [index] = await this.#archiveSource.getArchiveIndices([await tx.data.constants.historicalHeader.hash()]);
|
|
19
|
+
if (index === undefined) {
|
|
20
|
+
this.#log.warn(`Rejecting tx ${await Tx.getHash(tx)} for referencing an unknown block header`);
|
|
21
|
+
return { result: 'invalid', reason: ['Block header not found'] };
|
|
22
|
+
}
|
|
23
|
+
return { result: 'valid' };
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { MAX_FR_ARGS_TO_ALL_ENQUEUED_CALLS } from '@aztec/constants';
|
|
2
|
+
import { createLogger } from '@aztec/foundation/log';
|
|
3
|
+
import { Tx, type TxValidationResult, type TxValidator } from '@aztec/stdlib/tx';
|
|
4
|
+
|
|
5
|
+
export class DataTxValidator implements TxValidator<Tx> {
|
|
6
|
+
#log = createLogger('p2p:tx_validator:tx_data');
|
|
7
|
+
|
|
8
|
+
async validateTx(tx: Tx): Promise<TxValidationResult> {
|
|
9
|
+
const execRequestRes = this.#hasCorrectExecutionRequests(tx);
|
|
10
|
+
// Note: If we ever skip txs here, must change this return statement to account for them.
|
|
11
|
+
return (await execRequestRes).result === 'invalid' ? execRequestRes : this.#hasCorrectContractClassLogs(tx);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
async #hasCorrectExecutionRequests(tx: Tx): Promise<TxValidationResult> {
|
|
15
|
+
const callRequests = [
|
|
16
|
+
...tx.data.getRevertiblePublicCallRequests(),
|
|
17
|
+
...tx.data.getNonRevertiblePublicCallRequests(),
|
|
18
|
+
];
|
|
19
|
+
if (callRequests.length !== tx.enqueuedPublicFunctionCalls.length) {
|
|
20
|
+
this.#log.warn(
|
|
21
|
+
`Rejecting tx ${Tx.getHash(tx)} because of mismatch number of execution requests for public calls. Expected ${
|
|
22
|
+
callRequests.length
|
|
23
|
+
}. Got ${tx.enqueuedPublicFunctionCalls.length}.`,
|
|
24
|
+
);
|
|
25
|
+
return { result: 'invalid', reason: ['Wrong number of execution requests for public calls'] };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (tx.getTotalPublicArgsCount() > MAX_FR_ARGS_TO_ALL_ENQUEUED_CALLS) {
|
|
29
|
+
this.#log.warn(
|
|
30
|
+
`Rejecting tx ${await Tx.getHash(
|
|
31
|
+
tx,
|
|
32
|
+
)} because the total length of args to public enqueued calls is greater than ${MAX_FR_ARGS_TO_ALL_ENQUEUED_CALLS}`,
|
|
33
|
+
);
|
|
34
|
+
return { result: 'invalid', reason: ['Too many args in total to enqueued public calls'] };
|
|
35
|
+
}
|
|
36
|
+
const invalidExecutionRequestIndex = (
|
|
37
|
+
await Promise.all(
|
|
38
|
+
tx.enqueuedPublicFunctionCalls.map(
|
|
39
|
+
async (execRequest, i) => !(await execRequest.isForCallRequest(callRequests[i])),
|
|
40
|
+
),
|
|
41
|
+
)
|
|
42
|
+
).findIndex(Boolean);
|
|
43
|
+
if (invalidExecutionRequestIndex !== -1) {
|
|
44
|
+
this.#log.warn(
|
|
45
|
+
`Rejecting tx ${await Tx.getHash(
|
|
46
|
+
tx,
|
|
47
|
+
)} because of incorrect execution requests for public call at index ${invalidExecutionRequestIndex}.`,
|
|
48
|
+
);
|
|
49
|
+
return { result: 'invalid', reason: ['Incorrect execution request for public call'] };
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const teardownCallRequest = tx.data.getTeardownPublicCallRequest();
|
|
53
|
+
const isInvalidTeardownExecutionRequest =
|
|
54
|
+
(!teardownCallRequest && !tx.publicTeardownFunctionCall.isEmpty()) ||
|
|
55
|
+
(teardownCallRequest && !(await tx.publicTeardownFunctionCall.isForCallRequest(teardownCallRequest)));
|
|
56
|
+
if (isInvalidTeardownExecutionRequest) {
|
|
57
|
+
this.#log.warn(`Rejecting tx ${await Tx.getHash(tx)} because of incorrect teardown execution requests.`);
|
|
58
|
+
return { result: 'invalid', reason: ['Incorrect teardown execution request'] };
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return { result: 'valid' };
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async #hasCorrectContractClassLogs(tx: Tx): Promise<TxValidationResult> {
|
|
65
|
+
const contractClassLogsHashes = tx.data.getNonEmptyContractClassLogsHashes();
|
|
66
|
+
const hashedContractClasslogs = await Promise.all(tx.contractClassLogs.map(l => l.hash()));
|
|
67
|
+
if (contractClassLogsHashes.length !== hashedContractClasslogs.length) {
|
|
68
|
+
this.#log.warn(
|
|
69
|
+
`Rejecting tx ${Tx.getHash(tx)} because of mismatched number of contract class logs. Expected ${
|
|
70
|
+
contractClassLogsHashes.length
|
|
71
|
+
}. Got ${hashedContractClasslogs.length}.`,
|
|
72
|
+
);
|
|
73
|
+
return { result: 'invalid', reason: ['Mismatched number of contract class logs'] };
|
|
74
|
+
}
|
|
75
|
+
for (const [i, logHash] of contractClassLogsHashes.entries()) {
|
|
76
|
+
const hashedLog = hashedContractClasslogs[i];
|
|
77
|
+
if (!logHash.value.equals(hashedLog)) {
|
|
78
|
+
if (hashedContractClasslogs.some(l => logHash.value.equals(l))) {
|
|
79
|
+
const matchingLogIndex = hashedContractClasslogs.findIndex(l => logHash.value.equals(l));
|
|
80
|
+
this.#log.warn(
|
|
81
|
+
`Rejecting tx ${Tx.getHash(
|
|
82
|
+
tx,
|
|
83
|
+
)} because of mismatched contract class logs indices. Expected ${i} from the kernel's log hashes. Got ${matchingLogIndex} in the tx.`,
|
|
84
|
+
);
|
|
85
|
+
return { result: 'invalid', reason: ['Incorrectly sorted contract class logs'] };
|
|
86
|
+
} else {
|
|
87
|
+
this.#log.warn(
|
|
88
|
+
`Rejecting tx ${Tx.getHash(tx)} because of mismatched contract class logs. Expected hash ${
|
|
89
|
+
logHash.value
|
|
90
|
+
} from the kernels. Got ${hashedLog} in the tx.`,
|
|
91
|
+
);
|
|
92
|
+
return { result: 'invalid', reason: ['Mismatched contract class logs'] };
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
if (logHash.logHash.length !== tx.contractClassLogs[i].getEmittedLength()) {
|
|
96
|
+
this.#log.warn(
|
|
97
|
+
`Rejecting tx ${Tx.getHash(tx)} because of mismatched contract class logs length. Expected ${
|
|
98
|
+
logHash.logHash.length
|
|
99
|
+
} from the kernel's log hashes. Got ${tx.contractClassLogs[i].getEmittedLength()} in the tx.`,
|
|
100
|
+
);
|
|
101
|
+
return { result: 'invalid', reason: ['Mismatched contract class logs length'] };
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return { result: 'valid' };
|
|
105
|
+
}
|
|
106
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { createLogger } from '@aztec/foundation/log';
|
|
2
|
+
import { type AnyTx, Tx, type TxValidationResult, type TxValidator, hasPublicCalls } from '@aztec/stdlib/tx';
|
|
3
|
+
|
|
4
|
+
export interface NullifierSource {
|
|
5
|
+
nullifiersExist: (nullifiers: Buffer[]) => Promise<boolean[]>;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export class DoubleSpendTxValidator<T extends AnyTx> implements TxValidator<T> {
|
|
9
|
+
#log = createLogger('p2p:tx_validator:tx_double_spend');
|
|
10
|
+
#nullifierSource: NullifierSource;
|
|
11
|
+
|
|
12
|
+
constructor(nullifierSource: NullifierSource) {
|
|
13
|
+
this.#nullifierSource = nullifierSource;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async validateTx(tx: T): Promise<TxValidationResult> {
|
|
17
|
+
// Don't need to check for duplicate nullifiers if the tx has public calls
|
|
18
|
+
// because the AVM will perform merkle insertions as it goes and will fail on
|
|
19
|
+
// duplicate nullifier. In fact we CANNOT check here because the nullifiers
|
|
20
|
+
// have already been inserted, and so they will exist in nullifierSource.
|
|
21
|
+
if (!hasPublicCalls(tx)) {
|
|
22
|
+
const nullifiers = tx instanceof Tx ? tx.data.getNonEmptyNullifiers() : tx.txEffect.nullifiers;
|
|
23
|
+
|
|
24
|
+
// Ditch this tx if it has repeated nullifiers
|
|
25
|
+
const uniqueNullifiers = new Set(nullifiers);
|
|
26
|
+
if (uniqueNullifiers.size !== nullifiers.length) {
|
|
27
|
+
this.#log.warn(`Rejecting tx ${await Tx.getHash(tx)} for emitting duplicate nullifiers`);
|
|
28
|
+
return { result: 'invalid', reason: ['Duplicate nullifier in tx'] };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if ((await this.#nullifierSource.nullifiersExist(nullifiers.map(n => n.toBuffer()))).some(Boolean)) {
|
|
32
|
+
this.#log.warn(`Rejecting tx ${await Tx.getHash(tx)} for repeating a nullifier`);
|
|
33
|
+
return { result: 'invalid', reason: ['Existing nullifier'] };
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return { result: 'valid' };
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { Fr } from '@aztec/foundation/fields';
|
|
2
|
+
import { createLogger } from '@aztec/foundation/log';
|
|
3
|
+
import { type AnyTx, Tx, type TxValidationResult, type TxValidator } from '@aztec/stdlib/tx';
|
|
4
|
+
|
|
5
|
+
export class MetadataTxValidator<T extends AnyTx> implements TxValidator<T> {
|
|
6
|
+
#log = createLogger('p2p:tx_validator:tx_metadata');
|
|
7
|
+
|
|
8
|
+
constructor(private chainId: Fr, private blockNumber: Fr) {}
|
|
9
|
+
|
|
10
|
+
async validateTx(tx: T): Promise<TxValidationResult> {
|
|
11
|
+
const errors = [];
|
|
12
|
+
if (!(await this.#hasCorrectChainId(tx))) {
|
|
13
|
+
errors.push('Incorrect chain id');
|
|
14
|
+
}
|
|
15
|
+
if (!(await this.#isValidForBlockNumber(tx))) {
|
|
16
|
+
errors.push('Invalid block number');
|
|
17
|
+
}
|
|
18
|
+
return errors.length > 0 ? { result: 'invalid', reason: errors } : { result: 'valid' };
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async #hasCorrectChainId(tx: T): Promise<boolean> {
|
|
22
|
+
if (!tx.data.constants.txContext.chainId.equals(this.chainId)) {
|
|
23
|
+
this.#log.warn(
|
|
24
|
+
`Rejecting tx ${await Tx.getHash(
|
|
25
|
+
tx,
|
|
26
|
+
)} because of incorrect chain ${tx.data.constants.txContext.chainId.toNumber()} != ${this.chainId.toNumber()}`,
|
|
27
|
+
);
|
|
28
|
+
return false;
|
|
29
|
+
} else {
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async #isValidForBlockNumber(tx: T): Promise<boolean> {
|
|
35
|
+
const maxBlockNumber = tx.data.rollupValidationRequests.maxBlockNumber;
|
|
36
|
+
|
|
37
|
+
if (maxBlockNumber.isSome && maxBlockNumber.value < this.blockNumber) {
|
|
38
|
+
this.#log.warn(
|
|
39
|
+
`Rejecting tx ${await Tx.getHash(tx)} for low max block number. Tx max block number: ${
|
|
40
|
+
maxBlockNumber.value
|
|
41
|
+
}, current block number: ${this.blockNumber}.`,
|
|
42
|
+
);
|
|
43
|
+
return false;
|
|
44
|
+
} else {
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { createLogger } from '@aztec/foundation/log';
|
|
2
|
+
import type { ClientProtocolCircuitVerifier } from '@aztec/stdlib/interfaces/server';
|
|
3
|
+
import { Tx, type TxValidationResult, type TxValidator } from '@aztec/stdlib/tx';
|
|
4
|
+
|
|
5
|
+
export class TxProofValidator implements TxValidator<Tx> {
|
|
6
|
+
#log = createLogger('p2p:tx_validator:private_proof');
|
|
7
|
+
|
|
8
|
+
constructor(private verifier: ClientProtocolCircuitVerifier) {}
|
|
9
|
+
|
|
10
|
+
async validateTx(tx: Tx): Promise<TxValidationResult> {
|
|
11
|
+
if (!(await this.verifier.verifyProof(tx))) {
|
|
12
|
+
this.#log.warn(`Rejecting tx ${Tx.getHash(tx)} for invalid proof`);
|
|
13
|
+
return { result: 'invalid', reason: ['Invalid proof'] };
|
|
14
|
+
}
|
|
15
|
+
this.#log.trace(`Accepted ${Tx.getHash(tx)} with valid proof`);
|
|
16
|
+
return { result: 'valid' };
|
|
17
|
+
}
|
|
18
|
+
}
|