@aztec/p2p 0.0.1-commit.858058eac → 0.0.1-commit.85d7d01
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 +6 -6
- package/dest/client/factory.d.ts.map +1 -1
- package/dest/client/factory.js +23 -30
- package/dest/client/interface.d.ts +14 -19
- package/dest/client/interface.d.ts.map +1 -1
- package/dest/client/p2p_client.d.ts +9 -18
- package/dest/client/p2p_client.d.ts.map +1 -1
- package/dest/client/p2p_client.js +52 -72
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.js +6 -7
- package/dest/config.d.ts +13 -6
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +5 -5
- 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 +5 -2
- 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 +12 -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 +7 -5
- package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.d.ts +2 -2
- 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 +14 -6
- 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/index.d.ts +2 -2
- package/dest/mem_pools/tx_pool_v2/index.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/index.js +1 -1
- 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 +20 -6
- package/dest/mem_pools/tx_pool_v2/interfaces.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/interfaces.js +4 -1
- package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts +34 -8
- package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_metadata.js +76 -10
- 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 +36 -14
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts +9 -4
- 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 +13 -5
- 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 +297 -143
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts +2 -2
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.js +3 -3
- package/dest/msg_validators/tx_validator/factory.d.ts +114 -6
- package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/factory.js +219 -58
- package/dest/msg_validators/tx_validator/gas_validator.d.ts +58 -3
- package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/gas_validator.js +73 -36
- package/dest/msg_validators/tx_validator/index.d.ts +2 -1
- package/dest/msg_validators/tx_validator/index.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/index.js +1 -0
- package/dest/msg_validators/tx_validator/nullifier_cache.d.ts +14 -0
- package/dest/msg_validators/tx_validator/nullifier_cache.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/nullifier_cache.js +24 -0
- 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/dummy_service.d.ts +4 -4
- package/dest/services/dummy_service.d.ts.map +1 -1
- package/dest/services/dummy_service.js +4 -4
- package/dest/services/encoding.d.ts +2 -2
- package/dest/services/encoding.d.ts.map +1 -1
- package/dest/services/encoding.js +9 -8
- package/dest/services/gossipsub/topic_score_params.d.ts +18 -6
- package/dest/services/gossipsub/topic_score_params.d.ts.map +1 -1
- package/dest/services/gossipsub/topic_score_params.js +32 -10
- package/dest/services/libp2p/libp2p_service.d.ts +16 -13
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
- package/dest/services/libp2p/libp2p_service.js +69 -81
- 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 +19 -46
- 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/reqresp/batch-tx-requester/peer_collection.d.ts +17 -11
- package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts.map +1 -1
- package/dest/services/reqresp/batch-tx-requester/peer_collection.js +49 -15
- package/dest/services/reqresp/batch-tx-requester/tx_validator.js +2 -2
- package/dest/services/reqresp/reqresp.d.ts +1 -1
- package/dest/services/reqresp/reqresp.d.ts.map +1 -1
- package/dest/services/reqresp/reqresp.js +2 -1
- package/dest/services/service.d.ts +5 -3
- package/dest/services/service.d.ts.map +1 -1
- 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/services/tx_provider.d.ts +3 -3
- package/dest/services/tx_provider.d.ts.map +1 -1
- package/dest/services/tx_provider.js +4 -4
- package/dest/test-helpers/make-test-p2p-clients.d.ts +5 -6
- package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -1
- package/dest/test-helpers/make-test-p2p-clients.js +1 -2
- package/dest/test-helpers/mock-pubsub.d.ts +4 -4
- package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
- package/dest/test-helpers/mock-pubsub.js +8 -2
- package/dest/test-helpers/reqresp-nodes.d.ts +2 -3
- package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -1
- package/dest/test-helpers/reqresp-nodes.js +2 -2
- package/dest/test-helpers/testbench-utils.d.ts +8 -3
- 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 +13 -13
- package/dest/util.d.ts +2 -2
- package/dest/util.d.ts.map +1 -1
- package/package.json +14 -14
- package/src/client/factory.ts +39 -48
- package/src/client/interface.ts +17 -20
- package/src/client/p2p_client.ts +60 -104
- package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker.ts +19 -10
- package/src/config.ts +10 -10
- 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 +5 -2
- package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.ts +18 -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 +5 -5
- package/src/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.ts +14 -9
- 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/index.ts +1 -1
- package/src/mem_pools/tx_pool_v2/instrumentation.ts +69 -0
- package/src/mem_pools/tx_pool_v2/interfaces.ts +21 -6
- package/src/mem_pools/tx_pool_v2/tx_metadata.ts +107 -17
- package/src/mem_pools/tx_pool_v2/tx_pool_indices.ts +43 -16
- package/src/mem_pools/tx_pool_v2/tx_pool_v2.ts +18 -7
- package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +326 -138
- package/src/msg_validators/tx_validator/README.md +115 -0
- package/src/msg_validators/tx_validator/aggregate_tx_validator.ts +3 -3
- package/src/msg_validators/tx_validator/factory.ts +353 -77
- package/src/msg_validators/tx_validator/gas_validator.ts +90 -27
- package/src/msg_validators/tx_validator/index.ts +1 -0
- package/src/msg_validators/tx_validator/nullifier_cache.ts +30 -0
- package/src/msg_validators/tx_validator/timestamp_validator.ts +7 -7
- package/src/services/dummy_service.ts +6 -6
- package/src/services/encoding.ts +7 -7
- package/src/services/gossipsub/README.md +29 -14
- package/src/services/gossipsub/topic_score_params.ts +49 -13
- package/src/services/libp2p/libp2p_service.ts +80 -90
- package/src/services/reqresp/batch-tx-requester/batch_tx_requester.ts +20 -48
- 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/reqresp/batch-tx-requester/peer_collection.ts +63 -24
- package/src/services/reqresp/batch-tx-requester/tx_validator.ts +2 -2
- package/src/services/reqresp/reqresp.ts +3 -1
- package/src/services/service.ts +11 -2
- 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/services/tx_provider.ts +2 -2
- package/src/test-helpers/make-test-p2p-clients.ts +0 -2
- package/src/test-helpers/mock-pubsub.ts +13 -6
- package/src/test-helpers/reqresp-nodes.ts +2 -5
- package/src/test-helpers/testbench-utils.ts +11 -3
- package/src/testbench/p2p_client_testbench_worker.ts +22 -19
- package/src/util.ts +7 -1
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# Transaction Validation
|
|
2
|
+
|
|
3
|
+
This module defines the transaction validators and the factory functions that assemble them for each entry point into the system.
|
|
4
|
+
|
|
5
|
+
## Validation Strategy
|
|
6
|
+
|
|
7
|
+
Transactions enter the system through different paths. **Unsolicited** transactions (gossip and RPC) are fully validated before acceptance. **Solicited** transactions (req/resp and block proposals) are only checked for well-formedness because we must store them for block re-execution — they may ultimately be invalid, which is caught during block building and reported as part of block validation/attestation.
|
|
8
|
+
|
|
9
|
+
When solicited transactions fail to be mined, they may be migrated to the pending pool. At that point, the pool runs the state-dependent checks that were skipped on initial receipt.
|
|
10
|
+
|
|
11
|
+
## Entry Points
|
|
12
|
+
|
|
13
|
+
### 1. Gossip (libp2p pubsub)
|
|
14
|
+
|
|
15
|
+
**Factory**: `createFirstStageTxValidationsForGossipedTransactions` + `createSecondStageTxValidationsForGossipedTransactions`
|
|
16
|
+
**Called from**: `LibP2PService.handleGossipedTx()` in `libp2p_service.ts`
|
|
17
|
+
|
|
18
|
+
Unsolicited transactions from any peer. Fully validated in two stages with a pool pre-check in between to avoid wasting CPU on proof verification for transactions the pool would reject:
|
|
19
|
+
|
|
20
|
+
| Step | What runs | On failure |
|
|
21
|
+
|------|-----------|------------|
|
|
22
|
+
| **Stage 1** (fast) | TxPermitted, Data, Metadata, Timestamp, DoubleSpend, Gas, Phases, BlockHeader | Penalize peer, reject tx |
|
|
23
|
+
| **Pool pre-check** | `canAddPendingTx` — checks for duplicates, pool capacity | Ignore tx (no penalty) |
|
|
24
|
+
| **Stage 2** (slow) | Proof verification | Penalize peer, reject tx |
|
|
25
|
+
| **Pool add** | `addPendingTxs` | Accept, ignore, or reject |
|
|
26
|
+
|
|
27
|
+
Each stage-1 and stage-2 validator is paired with a `PeerErrorSeverity`. If a validator fails, the sending peer is penalized with that severity. The `doubleSpendValidator` has special handling: its severity is determined by how recently the nullifier appeared (recent = high tolerance, old = low tolerance).
|
|
28
|
+
|
|
29
|
+
### 2. JSON-RPC
|
|
30
|
+
|
|
31
|
+
**Factory**: `createTxValidatorForAcceptingTxsOverRPC`
|
|
32
|
+
**Called from**: `AztecNodeService.isValidTx()` in `aztec-node/server.ts`
|
|
33
|
+
|
|
34
|
+
Unsolicited transactions from a local wallet/PXE. Runs the full set of checks as a single aggregate validator:
|
|
35
|
+
|
|
36
|
+
- TxPermitted, Size, Data, Metadata, Timestamp, DoubleSpend, Phases, BlockHeader
|
|
37
|
+
- Gas (optional — skipped when `skipFeeEnforcement` is set)
|
|
38
|
+
- Proof verification (optional — skipped for simulations when no verifier is provided)
|
|
39
|
+
|
|
40
|
+
### 3. Req/resp and block proposals
|
|
41
|
+
|
|
42
|
+
**Factories**: `createTxValidatorForReqResponseReceivedTxs`, `createTxValidatorForBlockProposalReceivedTxs`
|
|
43
|
+
**Called from**: `LibP2PService.validateRequestedTx()`, `LibP2PService.validateTxsReceivedInBlockProposal()`, and `BatchRequestTxValidator` in `batch-tx-requester/tx_validator.ts`
|
|
44
|
+
|
|
45
|
+
Solicited transactions — we requested these from peers or received them as part of a block proposal we need to validate. We must accept them for re-execution even if they are invalid against the current state. Only well-formedness is checked:
|
|
46
|
+
|
|
47
|
+
- Metadata, Size, Data, Proof
|
|
48
|
+
|
|
49
|
+
State-dependent checks are deferred to either the block building validator (for txs included in blocks) or the pending pool migration validator (for unmined txs migrating to pending).
|
|
50
|
+
|
|
51
|
+
### 4. Block building
|
|
52
|
+
|
|
53
|
+
**Factory**: `createTxValidatorForBlockBuilding`
|
|
54
|
+
**Called from**: `CheckpointBuilder.makeBlockBuilderDeps()` in `validator-client/checkpoint_builder.ts`
|
|
55
|
+
|
|
56
|
+
Transactions already in the pool, about to be sequenced into a block. Re-validates against the current state of the block being built. **This is where invalid txs that entered via req/resp or block proposals are caught** — their invalidity is reported as part of block validation/attestation.
|
|
57
|
+
|
|
58
|
+
Runs:
|
|
59
|
+
- Timestamp, DoubleSpend, Phases, Gas, BlockHeader
|
|
60
|
+
|
|
61
|
+
Does **not** run:
|
|
62
|
+
- Proof, Data — already verified on entry (by gossip, RPC, or req/resp validators)
|
|
63
|
+
|
|
64
|
+
### 5. Pending pool migration
|
|
65
|
+
|
|
66
|
+
**Factory**: `createTxValidatorForTransactionsEnteringPendingTxPool`
|
|
67
|
+
**Called from**: `TxPoolV2Impl` (injected as the `createTxValidator` factory via `TxPoolV2Dependencies`)
|
|
68
|
+
|
|
69
|
+
When transactions that arrived via req/resp or block proposals fail to be mined, they may need to be included in our pending pool. These txs only had well-formedness checks on receipt, so the pool runs the state-dependent checks they missed before accepting them.
|
|
70
|
+
|
|
71
|
+
This validator is invoked on **every** transaction potentially entering the pending pool:
|
|
72
|
+
- `addPendingTxs` — validating each tx before adding
|
|
73
|
+
- `prepareForSlot` — unprotecting txs back to pending after a slot ends
|
|
74
|
+
- `handlePrunedBlocks` — unmining txs from pruned blocks back to pending
|
|
75
|
+
- Startup hydration — revalidating persisted non-mined txs on node restart
|
|
76
|
+
|
|
77
|
+
Runs:
|
|
78
|
+
- DoubleSpend, BlockHeader, GasLimits, Timestamp
|
|
79
|
+
|
|
80
|
+
Operates on `TxMetaData` (pre-built by the pool) rather than full `Tx` objects.
|
|
81
|
+
|
|
82
|
+
## Individual Validators
|
|
83
|
+
|
|
84
|
+
| Validator | What it checks | Benchmarked verification duration |
|
|
85
|
+
|-----------|---------------|---------------|
|
|
86
|
+
| `TxPermittedValidator` | Whether the system is accepting transactions (controlled by config flag) | 1.56 us |
|
|
87
|
+
| `DataTxValidator` | Transaction data integrity — correct structure, non-empty fields | 4.10–18.18 ms |
|
|
88
|
+
| `SizeTxValidator` | Transaction does not exceed maximum size limits | 2.28 us |
|
|
89
|
+
| `MetadataTxValidator` | Chain ID, rollup version, protocol contracts hash, VK tree root | 4.18 us |
|
|
90
|
+
| `TimestampTxValidator` | Transaction has not expired (expiration timestamp vs next slot) | 1.56 us |
|
|
91
|
+
| `DoubleSpendTxValidator` | Nullifiers do not already exist in the nullifier tree | 106.08 us |
|
|
92
|
+
| `GasTxValidator` | Gas limits are within bounds (delegates to `GasLimitsValidator`), max fee per gas meets current block fees, and fee payer has sufficient FeeJuice balance | 1.02 ms |
|
|
93
|
+
| `GasLimitsValidator` | Gas limits are >= fixed minimums and <= AVM max processable L2 gas. Used standalone in pool migration; also called internally by `GasTxValidator` | 3–10 us |
|
|
94
|
+
| `PhasesTxValidator` | Public function calls in setup phase are on the allow list | 10.12–13.12 us |
|
|
95
|
+
| `BlockHeaderTxValidator` | Transaction's anchor block hash exists in the archive tree | 98.88 us |
|
|
96
|
+
| `TxProofValidator` | Client proof verifies correctly | ~250ms |
|
|
97
|
+
|
|
98
|
+
## Validator Coverage by Entry Point
|
|
99
|
+
|
|
100
|
+
| Validator | Gossip | RPC | Req/resp | Block building | Pool migration |
|
|
101
|
+
|-----------|--------|-----|----------|----------------|----------------|
|
|
102
|
+
| TxPermitted | Stage 1 | Yes | — | — | — |
|
|
103
|
+
| Data | Stage 1 | Yes | Yes | — | — |
|
|
104
|
+
| Size | — | Yes | Yes | — | — |
|
|
105
|
+
| Metadata | Stage 1 | Yes | Yes | — | — |
|
|
106
|
+
| Timestamp | Stage 1 | Yes | — | Yes | Yes |
|
|
107
|
+
| DoubleSpend | Stage 1 | Yes | — | Yes | Yes |
|
|
108
|
+
| Gas (balance + limits) | Stage 1 | Optional* | — | Yes | — |
|
|
109
|
+
| GasLimits (standalone) | — | — | — | — | Yes |
|
|
110
|
+
| Phases | Stage 1 | Yes | — | Yes | — |
|
|
111
|
+
| BlockHeader | Stage 1 | Yes | — | Yes | Yes |
|
|
112
|
+
| Proof | Stage 2 | Optional** | Yes | — | — |
|
|
113
|
+
|
|
114
|
+
\* Gas balance check is skipped when `skipFeeEnforcement` is set (testing/dev). `GasTxValidator` internally delegates to `GasLimitsValidator` as its first step, so gas limits are checked wherever `GasTxValidator` runs. Pool migration uses `GasLimitsValidator` standalone because it doesn't need the balance or fee-per-gas checks.
|
|
115
|
+
\** Proof verification is skipped for simulations (no verifier provided).
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import type { TxValidationResult, TxValidator } from '@aztec/stdlib/tx';
|
|
2
2
|
|
|
3
3
|
export class AggregateTxValidator<T> implements TxValidator<T> {
|
|
4
|
-
|
|
4
|
+
readonly validators: TxValidator<T>[];
|
|
5
5
|
constructor(...validators: TxValidator<T>[]) {
|
|
6
6
|
if (validators.length === 0) {
|
|
7
7
|
throw new Error('At least one validator must be provided');
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
this
|
|
10
|
+
this.validators = validators;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
async validateTx(tx: T): Promise<TxValidationResult> {
|
|
14
14
|
const aggregate: { result: string; reason?: string[] } = { result: 'valid', reason: [] };
|
|
15
|
-
for (const validator of this
|
|
15
|
+
for (const validator of this.validators) {
|
|
16
16
|
const result = await validator.validateTx(tx);
|
|
17
17
|
if (result.result === 'invalid') {
|
|
18
18
|
aggregate.result = 'invalid';
|
|
@@ -1,41 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Transaction validator factories for each tx entry point.
|
|
3
|
+
*
|
|
4
|
+
* Unsolicited transactions (gossip and RPC) are fully validated before acceptance.
|
|
5
|
+
* Transactions received via req/resp or block proposals are only checked for
|
|
6
|
+
* well-formedness because we must include them for block re-execution — they may
|
|
7
|
+
* ultimately be invalid, which is caught during block building and reported as
|
|
8
|
+
* part of block validation/attestation. See the README in this directory for the
|
|
9
|
+
* full validation strategy.
|
|
10
|
+
*
|
|
11
|
+
* 1. **Gossip** — full validation in two stages with a pool pre-check in between.
|
|
12
|
+
* Stage 1 (fast): metadata, data, timestamps, double-spend, gas, phases, block header.
|
|
13
|
+
* Pool pre-check: `canAddPendingTx` — skips proof verification if pool would reject.
|
|
14
|
+
* Stage 2 (slow): proof verification.
|
|
15
|
+
* Orchestrated by `handleGossipedTx` in `libp2p_service.ts`.
|
|
16
|
+
*
|
|
17
|
+
* 2. **JSON-RPC** — full validation including all state-dependent checks.
|
|
18
|
+
* Proof verification and fee enforcement are configurable for testing purposes.
|
|
19
|
+
*
|
|
20
|
+
* 3. **Req/resp & block proposals** — well-formedness checks only (metadata, size,
|
|
21
|
+
* data, proof). Stored for re-execution; validity against state is not checked here.
|
|
22
|
+
*
|
|
23
|
+
* 4. **Block building** — re-validates against current state immediately before
|
|
24
|
+
* sequencing. Catches invalid txs that entered via req/resp or block proposals.
|
|
25
|
+
* Proof and data checks are skipped since they were verified on entry.
|
|
26
|
+
*
|
|
27
|
+
* 5. **Pending pool migration** — when unmined txs (e.g. from req/resp or block
|
|
28
|
+
* proposals) are migrated to the pending pool, the pool runs the state-dependent
|
|
29
|
+
* checks they missed: double-spend, block header, gas limits, and timestamps.
|
|
30
|
+
* This runs on every tx potentially entering the pending pool.
|
|
31
|
+
*/
|
|
1
32
|
import { BlockNumber } from '@aztec/foundation/branded-types';
|
|
2
33
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
3
34
|
import type { LoggerBindings } from '@aztec/foundation/log';
|
|
4
35
|
import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vk-tree';
|
|
5
36
|
import { ProtocolContractAddress, protocolContractsHash } from '@aztec/protocol-contracts';
|
|
37
|
+
import type { BlockHash } from '@aztec/stdlib/block';
|
|
6
38
|
import type { ContractDataSource } from '@aztec/stdlib/contract';
|
|
7
39
|
import type { GasFees } from '@aztec/stdlib/gas';
|
|
8
40
|
import type {
|
|
9
41
|
AllowedElement,
|
|
10
42
|
ClientProtocolCircuitVerifier,
|
|
43
|
+
MerkleTreeReadOperations,
|
|
44
|
+
PublicProcessorValidator,
|
|
11
45
|
WorldStateSynchronizer,
|
|
12
46
|
} from '@aztec/stdlib/interfaces/server';
|
|
13
47
|
import { PeerErrorSeverity } from '@aztec/stdlib/p2p';
|
|
14
|
-
import { DatabasePublicStateSource, MerkleTreeId } from '@aztec/stdlib/trees';
|
|
15
|
-
import type { Tx, TxValidationResult, TxValidator } from '@aztec/stdlib/tx';
|
|
48
|
+
import { DatabasePublicStateSource, MerkleTreeId, type PublicStateSource } from '@aztec/stdlib/trees';
|
|
49
|
+
import type { GlobalVariables, Tx, TxValidationResult, TxValidator } from '@aztec/stdlib/tx';
|
|
16
50
|
import type { UInt64 } from '@aztec/stdlib/types';
|
|
17
51
|
|
|
52
|
+
import type { TxMetaData } from '../../mem_pools/tx_pool_v2/tx_metadata.js';
|
|
18
53
|
import { AggregateTxValidator } from './aggregate_tx_validator.js';
|
|
19
54
|
import { ArchiveCache } from './archive_cache.js';
|
|
20
|
-
import { BlockHeaderTxValidator } from './block_header_validator.js';
|
|
55
|
+
import { type ArchiveSource, BlockHeaderTxValidator } from './block_header_validator.js';
|
|
21
56
|
import { DataTxValidator } from './data_validator.js';
|
|
22
|
-
import { DoubleSpendTxValidator } from './double_spend_validator.js';
|
|
23
|
-
import { GasTxValidator } from './gas_validator.js';
|
|
57
|
+
import { DoubleSpendTxValidator, type NullifierSource } from './double_spend_validator.js';
|
|
58
|
+
import { GasLimitsValidator, GasTxValidator } from './gas_validator.js';
|
|
24
59
|
import { MetadataTxValidator } from './metadata_validator.js';
|
|
60
|
+
import { NullifierCache } from './nullifier_cache.js';
|
|
25
61
|
import { PhasesTxValidator } from './phases_validator.js';
|
|
26
62
|
import { SizeTxValidator } from './size_validator.js';
|
|
27
63
|
import { TimestampTxValidator } from './timestamp_validator.js';
|
|
28
64
|
import { TxPermittedValidator } from './tx_permitted_validator.js';
|
|
29
65
|
import { TxProofValidator } from './tx_proof_validator.js';
|
|
30
66
|
|
|
31
|
-
|
|
67
|
+
/**
|
|
68
|
+
* A validator paired with a peer penalty severity.
|
|
69
|
+
* Used for gossip validation where each validator's failure triggers a peer penalization
|
|
70
|
+
* with the associated severity level.
|
|
71
|
+
*/
|
|
72
|
+
export interface TransactionValidator {
|
|
32
73
|
validator: {
|
|
33
74
|
validateTx(tx: Tx): Promise<TxValidationResult>;
|
|
34
75
|
};
|
|
35
76
|
severity: PeerErrorSeverity;
|
|
36
77
|
}
|
|
37
78
|
|
|
38
|
-
|
|
79
|
+
/**
|
|
80
|
+
* First stage of gossip validation — fast checks run before the pool pre-check.
|
|
81
|
+
*
|
|
82
|
+
* If any validator fails, the peer is penalized and the tx is rejected immediately,
|
|
83
|
+
* without consulting the pool or running proof verification.
|
|
84
|
+
*
|
|
85
|
+
* The `doubleSpendValidator` failure is special-cased by the caller (`handleGossipedTx`)
|
|
86
|
+
* to determine severity based on how recently the nullifier appeared.
|
|
87
|
+
*/
|
|
88
|
+
export function createFirstStageTxValidationsForGossipedTransactions(
|
|
39
89
|
timestamp: UInt64,
|
|
40
90
|
blockNumber: BlockNumber,
|
|
41
91
|
worldStateSynchronizer: WorldStateSynchronizer,
|
|
@@ -44,86 +94,106 @@ export function createTxMessageValidators(
|
|
|
44
94
|
rollupVersion: number,
|
|
45
95
|
protocolContractsHash: Fr,
|
|
46
96
|
contractDataSource: ContractDataSource,
|
|
47
|
-
proofVerifier: ClientProtocolCircuitVerifier,
|
|
48
97
|
txsPermitted: boolean,
|
|
49
98
|
allowedInSetup: AllowedElement[] = [],
|
|
50
99
|
bindings?: LoggerBindings,
|
|
51
|
-
): Record<string,
|
|
100
|
+
): Record<string, TransactionValidator> {
|
|
52
101
|
const merkleTree = worldStateSynchronizer.getCommitted();
|
|
53
102
|
|
|
54
|
-
return
|
|
55
|
-
{
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
103
|
+
return {
|
|
104
|
+
timestampValidator: {
|
|
105
|
+
validator: new TimestampTxValidator<Tx>(
|
|
106
|
+
{
|
|
107
|
+
timestamp,
|
|
108
|
+
blockNumber,
|
|
109
|
+
},
|
|
110
|
+
bindings,
|
|
111
|
+
),
|
|
112
|
+
severity: PeerErrorSeverity.HighToleranceError,
|
|
113
|
+
},
|
|
114
|
+
txsPermittedValidator: {
|
|
115
|
+
validator: new TxPermittedValidator(txsPermitted, bindings),
|
|
116
|
+
severity: PeerErrorSeverity.MidToleranceError,
|
|
117
|
+
},
|
|
118
|
+
txSizeValidator: {
|
|
119
|
+
validator: new SizeTxValidator(bindings),
|
|
120
|
+
severity: PeerErrorSeverity.MidToleranceError,
|
|
121
|
+
},
|
|
122
|
+
metadataValidator: {
|
|
123
|
+
validator: new MetadataTxValidator(
|
|
124
|
+
{
|
|
125
|
+
l1ChainId: new Fr(l1ChainId),
|
|
126
|
+
rollupVersion: new Fr(rollupVersion),
|
|
127
|
+
protocolContractsHash,
|
|
128
|
+
vkTreeRoot: getVKTreeRoot(),
|
|
129
|
+
},
|
|
130
|
+
bindings,
|
|
131
|
+
),
|
|
132
|
+
severity: PeerErrorSeverity.MidToleranceError,
|
|
133
|
+
},
|
|
134
|
+
phasesValidator: {
|
|
135
|
+
validator: new PhasesTxValidator(contractDataSource, allowedInSetup, timestamp, bindings),
|
|
136
|
+
severity: PeerErrorSeverity.MidToleranceError,
|
|
137
|
+
},
|
|
138
|
+
blockHeaderValidator: {
|
|
139
|
+
validator: new BlockHeaderTxValidator(new ArchiveCache(merkleTree), bindings),
|
|
140
|
+
severity: PeerErrorSeverity.HighToleranceError,
|
|
141
|
+
},
|
|
142
|
+
doubleSpendValidator: {
|
|
143
|
+
validator: new DoubleSpendTxValidator(
|
|
144
|
+
{
|
|
145
|
+
nullifiersExist: async (nullifiers: Buffer[]) => {
|
|
146
|
+
const merkleTree = worldStateSynchronizer.getCommitted();
|
|
147
|
+
const indices = await merkleTree.findLeafIndices(MerkleTreeId.NULLIFIER_TREE, nullifiers);
|
|
148
|
+
return indices.map(index => index !== undefined);
|
|
94
149
|
},
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
gasValidator: {
|
|
100
|
-
validator: new GasTxValidator(
|
|
101
|
-
new DatabasePublicStateSource(merkleTree),
|
|
102
|
-
ProtocolContractAddress.FeeJuice,
|
|
103
|
-
gasFees,
|
|
104
|
-
bindings,
|
|
105
|
-
),
|
|
106
|
-
severity: PeerErrorSeverity.HighToleranceError,
|
|
107
|
-
},
|
|
108
|
-
phasesValidator: {
|
|
109
|
-
validator: new PhasesTxValidator(contractDataSource, allowedInSetup, timestamp, bindings),
|
|
110
|
-
severity: PeerErrorSeverity.MidToleranceError,
|
|
111
|
-
},
|
|
112
|
-
blockHeaderValidator: {
|
|
113
|
-
validator: new BlockHeaderTxValidator(new ArchiveCache(merkleTree), bindings),
|
|
114
|
-
severity: PeerErrorSeverity.HighToleranceError,
|
|
115
|
-
},
|
|
150
|
+
},
|
|
151
|
+
bindings,
|
|
152
|
+
),
|
|
153
|
+
severity: PeerErrorSeverity.MidToleranceError, // This is handled specifically at the point of rejection by considering a recent window where it may have been valid
|
|
116
154
|
},
|
|
117
|
-
{
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
155
|
+
gasValidator: {
|
|
156
|
+
validator: new GasTxValidator(
|
|
157
|
+
new DatabasePublicStateSource(merkleTree),
|
|
158
|
+
ProtocolContractAddress.FeeJuice,
|
|
159
|
+
gasFees,
|
|
160
|
+
bindings,
|
|
161
|
+
),
|
|
162
|
+
severity: PeerErrorSeverity.MidToleranceError,
|
|
122
163
|
},
|
|
123
|
-
|
|
164
|
+
dataValidator: {
|
|
165
|
+
validator: new DataTxValidator(bindings),
|
|
166
|
+
severity: PeerErrorSeverity.MidToleranceError,
|
|
167
|
+
},
|
|
168
|
+
};
|
|
124
169
|
}
|
|
125
170
|
|
|
126
|
-
|
|
171
|
+
/**
|
|
172
|
+
* Second stage of gossip validation — expensive proof verification.
|
|
173
|
+
*
|
|
174
|
+
* Only runs after the first stage passes AND `canAddPendingTx` confirms the pool would
|
|
175
|
+
* accept the tx. This avoids wasting CPU on proof verification for txs the pool would reject
|
|
176
|
+
* (e.g., duplicates, insufficient balance, pool full).
|
|
177
|
+
*/
|
|
178
|
+
export function createSecondStageTxValidationsForGossipedTransactions(
|
|
179
|
+
proofVerifier: ClientProtocolCircuitVerifier,
|
|
180
|
+
bindings?: LoggerBindings,
|
|
181
|
+
): Record<string, TransactionValidator> {
|
|
182
|
+
return {
|
|
183
|
+
proofValidator: {
|
|
184
|
+
validator: new TxProofValidator(proofVerifier, bindings),
|
|
185
|
+
severity: PeerErrorSeverity.LowToleranceError,
|
|
186
|
+
},
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Well-formedness checks only: metadata, size, data, and proof.
|
|
192
|
+
* Used for req/resp and block proposal txs. These txs must be accepted for block
|
|
193
|
+
* re-execution even though they may be invalid against current state — that is
|
|
194
|
+
* caught later by the block building validator.
|
|
195
|
+
*/
|
|
196
|
+
function createTxValidatorForMinimumTxIntegrityChecks(
|
|
127
197
|
verifier: ClientProtocolCircuitVerifier,
|
|
128
198
|
{
|
|
129
199
|
l1ChainId,
|
|
@@ -149,3 +219,209 @@ export function createTxReqRespValidator(
|
|
|
149
219
|
new TxProofValidator(verifier, bindings),
|
|
150
220
|
);
|
|
151
221
|
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Validators for txs received via req/resp or filestores.
|
|
225
|
+
* Checks well-formedness only — we must accept these for re-execution even if they
|
|
226
|
+
* are invalid against current state. State-dependent checks happen when the tx
|
|
227
|
+
* enters the pending pool or during block building.
|
|
228
|
+
*/
|
|
229
|
+
export function createTxValidatorForReqResponseReceivedTxs(
|
|
230
|
+
verifier: ClientProtocolCircuitVerifier,
|
|
231
|
+
{
|
|
232
|
+
l1ChainId,
|
|
233
|
+
rollupVersion,
|
|
234
|
+
}: {
|
|
235
|
+
l1ChainId: number;
|
|
236
|
+
rollupVersion: number;
|
|
237
|
+
},
|
|
238
|
+
bindings?: LoggerBindings,
|
|
239
|
+
): TxValidator {
|
|
240
|
+
return createTxValidatorForMinimumTxIntegrityChecks(verifier, { l1ChainId, rollupVersion }, bindings);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Validators for txs received in block proposals.
|
|
245
|
+
* Same as req/resp — well-formedness only. We must store these for block
|
|
246
|
+
* re-execution; their validity against state is checked during block building.
|
|
247
|
+
*/
|
|
248
|
+
export function createTxValidatorForBlockProposalReceivedTxs(
|
|
249
|
+
verifier: ClientProtocolCircuitVerifier,
|
|
250
|
+
{
|
|
251
|
+
l1ChainId,
|
|
252
|
+
rollupVersion,
|
|
253
|
+
}: {
|
|
254
|
+
l1ChainId: number;
|
|
255
|
+
rollupVersion: number;
|
|
256
|
+
},
|
|
257
|
+
bindings?: LoggerBindings,
|
|
258
|
+
): TxValidator {
|
|
259
|
+
return createTxValidatorForMinimumTxIntegrityChecks(verifier, { l1ChainId, rollupVersion }, bindings);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Validators for unsolicited txs received over JSON-RPC (from a local wallet/PXE).
|
|
264
|
+
* Full validation — all state-dependent checks are run. Proof verification is optional
|
|
265
|
+
* (can be skipped for testing purposes). Fee enforcement is also optional (skipped for testing/dev).
|
|
266
|
+
* Called from `AztecNodeService.isValidTx()`.
|
|
267
|
+
*/
|
|
268
|
+
export function createTxValidatorForAcceptingTxsOverRPC(
|
|
269
|
+
db: MerkleTreeReadOperations,
|
|
270
|
+
contractDataSource: ContractDataSource,
|
|
271
|
+
verifier: ClientProtocolCircuitVerifier | undefined,
|
|
272
|
+
{
|
|
273
|
+
l1ChainId,
|
|
274
|
+
rollupVersion,
|
|
275
|
+
setupAllowList,
|
|
276
|
+
gasFees,
|
|
277
|
+
skipFeeEnforcement,
|
|
278
|
+
timestamp,
|
|
279
|
+
blockNumber,
|
|
280
|
+
txsPermitted,
|
|
281
|
+
}: {
|
|
282
|
+
l1ChainId: number;
|
|
283
|
+
rollupVersion: number;
|
|
284
|
+
setupAllowList: AllowedElement[];
|
|
285
|
+
gasFees: GasFees;
|
|
286
|
+
skipFeeEnforcement?: boolean;
|
|
287
|
+
timestamp: UInt64;
|
|
288
|
+
blockNumber: BlockNumber;
|
|
289
|
+
txsPermitted: boolean;
|
|
290
|
+
},
|
|
291
|
+
bindings?: LoggerBindings,
|
|
292
|
+
): TxValidator<Tx> {
|
|
293
|
+
const validators: TxValidator<Tx>[] = [
|
|
294
|
+
new TxPermittedValidator(txsPermitted, bindings),
|
|
295
|
+
new TimestampTxValidator(
|
|
296
|
+
{
|
|
297
|
+
timestamp,
|
|
298
|
+
blockNumber,
|
|
299
|
+
},
|
|
300
|
+
bindings,
|
|
301
|
+
),
|
|
302
|
+
new SizeTxValidator(bindings),
|
|
303
|
+
new MetadataTxValidator(
|
|
304
|
+
{
|
|
305
|
+
l1ChainId: new Fr(l1ChainId),
|
|
306
|
+
rollupVersion: new Fr(rollupVersion),
|
|
307
|
+
protocolContractsHash,
|
|
308
|
+
vkTreeRoot: getVKTreeRoot(),
|
|
309
|
+
},
|
|
310
|
+
bindings,
|
|
311
|
+
),
|
|
312
|
+
new PhasesTxValidator(contractDataSource, setupAllowList, timestamp, bindings),
|
|
313
|
+
new BlockHeaderTxValidator(new ArchiveCache(db), bindings),
|
|
314
|
+
new DoubleSpendTxValidator(new NullifierCache(db), bindings),
|
|
315
|
+
new DataTxValidator(bindings),
|
|
316
|
+
];
|
|
317
|
+
|
|
318
|
+
if (!skipFeeEnforcement) {
|
|
319
|
+
validators.push(
|
|
320
|
+
new GasTxValidator(new DatabasePublicStateSource(db), ProtocolContractAddress.FeeJuice, gasFees, bindings),
|
|
321
|
+
);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
if (verifier) {
|
|
325
|
+
validators.push(new TxProofValidator(verifier, bindings));
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
return new AggregateTxValidator(...validators);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* Validators for txs about to be included in a block by the sequencer.
|
|
333
|
+
* Re-validates against current state. This is where invalid txs that entered via
|
|
334
|
+
* req/resp or block proposals are caught — their invalidity is reported as part
|
|
335
|
+
* of block validation/attestation. Proof and data checks are omitted since they
|
|
336
|
+
* were already verified on entry.
|
|
337
|
+
* Called from `CheckpointBuilder.makeBlockBuilderDeps()`.
|
|
338
|
+
*/
|
|
339
|
+
export function createTxValidatorForBlockBuilding(
|
|
340
|
+
db: MerkleTreeReadOperations,
|
|
341
|
+
contractDataSource: ContractDataSource,
|
|
342
|
+
globalVariables: GlobalVariables,
|
|
343
|
+
setupAllowList: AllowedElement[],
|
|
344
|
+
bindings?: LoggerBindings,
|
|
345
|
+
): PublicProcessorValidator {
|
|
346
|
+
const nullifierCache = new NullifierCache(db);
|
|
347
|
+
const archiveCache = new ArchiveCache(db);
|
|
348
|
+
const publicStateSource = new DatabasePublicStateSource(db);
|
|
349
|
+
|
|
350
|
+
return {
|
|
351
|
+
preprocessValidator: createTxValidatorForValidatingAgainstCurrentState(
|
|
352
|
+
nullifierCache,
|
|
353
|
+
archiveCache,
|
|
354
|
+
publicStateSource,
|
|
355
|
+
contractDataSource,
|
|
356
|
+
globalVariables,
|
|
357
|
+
setupAllowList,
|
|
358
|
+
bindings,
|
|
359
|
+
),
|
|
360
|
+
nullifierCache,
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
function createTxValidatorForValidatingAgainstCurrentState(
|
|
365
|
+
nullifierSource: NullifierSource,
|
|
366
|
+
archiveSource: ArchiveSource,
|
|
367
|
+
publicStateSource: PublicStateSource,
|
|
368
|
+
contractDataSource: ContractDataSource,
|
|
369
|
+
globalVariables: GlobalVariables,
|
|
370
|
+
setupAllowList: AllowedElement[],
|
|
371
|
+
bindings?: LoggerBindings,
|
|
372
|
+
): TxValidator<Tx> {
|
|
373
|
+
// We don't include the TxProofValidator nor the DataTxValidator here because they are already checked by the time we get to block building.
|
|
374
|
+
return new AggregateTxValidator(
|
|
375
|
+
new TimestampTxValidator(
|
|
376
|
+
{
|
|
377
|
+
timestamp: globalVariables.timestamp,
|
|
378
|
+
blockNumber: globalVariables.blockNumber,
|
|
379
|
+
},
|
|
380
|
+
bindings,
|
|
381
|
+
),
|
|
382
|
+
new PhasesTxValidator(contractDataSource, setupAllowList, globalVariables.timestamp, bindings),
|
|
383
|
+
new BlockHeaderTxValidator(archiveSource, bindings),
|
|
384
|
+
new DoubleSpendTxValidator(nullifierSource, bindings),
|
|
385
|
+
new GasTxValidator(publicStateSource, ProtocolContractAddress.FeeJuice, globalVariables.gasFees, bindings),
|
|
386
|
+
);
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* Validators for txs migrating to the pending pool.
|
|
391
|
+
*
|
|
392
|
+
* Txs that arrived via req/resp or block proposals only had well-formedness checks
|
|
393
|
+
* on receipt. When they fail to be mined and are migrated to the pending pool, we
|
|
394
|
+
* run the state-dependent checks they missed: double-spend, block header, gas limits,
|
|
395
|
+
* and timestamp expiry. This is run on EVERY tx potentially entering the pending pool
|
|
396
|
+
* — called inside `TxPoolV2Impl` during `addPendingTxs`, `prepareForSlot` (unprotect),
|
|
397
|
+
* `handlePrunedBlocks` (unmine), and startup hydration.
|
|
398
|
+
*
|
|
399
|
+
* Operates on `TxMetaData` rather than full `Tx` since metadata is pre-built by the pool.
|
|
400
|
+
* Injected into `TxPoolV2` as the `createTxValidator` factory in `TxPoolV2Dependencies`.
|
|
401
|
+
*/
|
|
402
|
+
export async function createTxValidatorForTransactionsEnteringPendingTxPool(
|
|
403
|
+
worldStateSynchronizer: WorldStateSynchronizer,
|
|
404
|
+
timestamp: bigint,
|
|
405
|
+
blockNumber: BlockNumber,
|
|
406
|
+
bindings?: LoggerBindings,
|
|
407
|
+
): Promise<TxValidator<TxMetaData>> {
|
|
408
|
+
await worldStateSynchronizer.syncImmediate();
|
|
409
|
+
const merkleTree = worldStateSynchronizer.getCommitted();
|
|
410
|
+
const nullifierSource: NullifierSource = {
|
|
411
|
+
nullifiersExist: async (nullifiers: Buffer[]) => {
|
|
412
|
+
const indices = await merkleTree.findLeafIndices(MerkleTreeId.NULLIFIER_TREE, nullifiers);
|
|
413
|
+
return indices.map(index => index !== undefined);
|
|
414
|
+
},
|
|
415
|
+
};
|
|
416
|
+
const archiveSource: ArchiveSource = {
|
|
417
|
+
getArchiveIndices: (archives: BlockHash[]) => {
|
|
418
|
+
return merkleTree.findLeafIndices(MerkleTreeId.ARCHIVE, archives);
|
|
419
|
+
},
|
|
420
|
+
};
|
|
421
|
+
return new AggregateTxValidator<TxMetaData>(
|
|
422
|
+
new GasLimitsValidator<TxMetaData>(bindings),
|
|
423
|
+
new TimestampTxValidator<TxMetaData>({ timestamp, blockNumber }, bindings),
|
|
424
|
+
new DoubleSpendTxValidator<TxMetaData>(nullifierSource, bindings),
|
|
425
|
+
new BlockHeaderTxValidator<TxMetaData>(archiveSource, bindings),
|
|
426
|
+
);
|
|
427
|
+
}
|